launching events from a thread

M

MIke Brown

Hello all,

I've been searching for a solution on google for a problem related to
creating events from a worker thread, with no luck..

Basically, the problem is when my events are caught by a UI using my
class, they get the usual "Control 'blah' accessed from a thread other
than the thread it was created on.". I understand that of course, but
my class is to be distributed to people who don't want to have to worry
about invoking delegates in the event handler, I want to keep it all
neat and tidy inside the class and they can do whatever they want in
the events I throw. Is there a way to launch my event on the thread the
class was created on, instead of my worker thread? I've tried using a
delegate thinking that would work, but it doesn't. I've also tried
inheriting from Control and using Invoke, which doesn't seem to work as
well.

Is there something I'm missing to easily accomplish this within my
class?

<?
.....
public myclass()
{
readThread = new Thread(new ThreadStart(ThreadLoop));
}

public void ThreadLoop()
{
while(some waithandle)
{
if(something)
if(myevent!=null) myevent(this, new args(1,2,3,4));
// instead of calling the above event here, I need to trigger
something
// in the thread the class was created on (UI Thread).
}
}
.....
?>

Thanks!

Michael Brown
360 Replays Ltd.
 
A

Andreas Mueller

MIke said:
Hello all,

I've been searching for a solution on google for a problem related to
creating events from a worker thread, with no luck..

Basically, the problem is when my events are caught by a UI using my
class, they get the usual "Control 'blah' accessed from a thread other
than the thread it was created on.". I understand that of course, but
my class is to be distributed to people who don't want to have to worry
about invoking delegates in the event handler, I want to keep it all
neat and tidy inside the class and they can do whatever they want in
the events I throw. Is there a way to launch my event on the thread the
class was created on, instead of my worker thread? I've tried using a
delegate thinking that would work, but it doesn't. I've also tried
inheriting from Control and using Invoke, which doesn't seem to work as
well.

Is there something I'm missing to easily accomplish this within my
class?

<?
....
public myclass()
{
readThread = new Thread(new ThreadStart(ThreadLoop));
}

public void ThreadLoop()
{
while(some waithandle)
{
if(something)
if(myevent!=null) myevent(this, new args(1,2,3,4));
// instead of calling the above event here, I need to trigger
something
// in the thread the class was created on (UI Thread).
}
}
....
?>

Thanks!

Michael Brown
360 Replays Ltd.

Hi,

You need to have access to one of your UI Controls inside your thread.
This enables you to invoke your delegate in the UI thread. I can think
of 2 ways to do this:

(1)
In my applications I usually have some sort of service for this, which
is initialized at startup:

using System;
using System.Threading;
using System.Windows.Forms;

namespace ConsoleApplication
{
static class ApplicationHost
{
public static void Invoke(Delegate method, params object[] args)
{
aControlInTheUiThread.Invoke(method, args);
}
public static void BeginInvoke(Delegate method,
params object[] args)
{
aControlInTheUiThread.BeginInvoke(method, args);
}


// initialiaized at startup
private static Control aControlInTheUiThread;
}
class Program
{

static void Main()
{
ThreadHelper helper = new ThreadHelper();
Thread readThread =
new Thread(new ThreadStart(helper.ThreadLoop));
}


}

class ThreadHelper
{
private bool something = false;
public EventHandler SomeEvent;
public void ThreadLoop()
{
while(true)
{
if(something)
{
ApplicationHost.Invoke(
new RaiseSomeEventInUiThreadHandler(
RaiseSomeEventInUiThread)
;
}
}
}
private delegate void RaiseSomeEventInUiThreadHandler();
private void RaiseSomeEventInUiThread()
{
if (SomeEvent != null)
SomeEvent(this, EventArgs.Empty);
}
}
}

(2)
Pass a control as an argument into your thread:

namespace ConsoleApplication
{

class Program
{
static void Main()
{
Control ctrl = null;// Some control of the GUI,
// e.g. main form
ThreadHelper helper = new ThreadHelper(ctrl);
Thread readThread =
new Thread(new ThreadStart(helper.ThreadLoop));
}
}

class ThreadHelper
{
public ThreadHelper(Control ctrlInUiThread)
{
this.ctrlInUiThread = ctrlInUiThread;
}
private Control ctrlInUiThread;
private bool something = false;
public EventHandler SomeEvent;
public void ThreadLoop()
{
while(true)
{
if(something)
{
ctrlInUiThread.Invoke(
new RaiseSomeEventInUiThreadHandler(
RaiseSomeEventInUiThread)
);
}
}
}
private delegate void RaiseSomeEventInUiThreadHandler();
private void RaiseSomeEventInUiThread()
{
if (SomeEvent != null)
SomeEvent(this, EventArgs.Empty);
}
}
}

HTH,
Andy
 
M

Marc Gravell

A minor obo; to use Invoke and BeginInvoke you can actually limit to the
ISynchronizeInvoke interface, rather than Control - but still pass a control
in as the object to provide this interface.
Not only is this more abstract, but in a partitioned assembly model it means
you don't need to reference the windows.forms assembly from your console
wrapper, as this is in the "System" assembly (System.ComponentModel
namespace).

But it works either way ;-p

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Asynchronous event 2
Thread 1
Delegates/events 8
Problem while Stopping the thread 2
How to raise an event in UI thread? 4
Events - thread safe? 5
Events problem 4
Thread 7

Top