Is there any easy scheme for handling event from another thread thanthe UI?

S

Sin Jeong-hun

Hello.

Event handlers for events from an object of another thread than the UI
thread cannot access UI components, as you know. If the object has
many events this precedure is painstaking. Plus the source code gets
longer and dirtier.

Note :The code below is NOT the actual code, but an example. (I say
this, because sometimes people points out that the sample code won't
complie, even if it's just an example to explain the matter. ... means
there are more codes but are omitted because those are unnecessary.)

public delegate void MessageDelegate(Worker sender, Data d);
class ObjectFromAnotherThread
{
public event MessageDelegate MessageReceived;
....
MessageReceived(this, d);
....
}
class MainForm:Form
{
....
void OnMessage(Worker sender, Data d)
{
if (InvokeRequired)
{
OnMessageDelegate d = new OnMessageDelegate(OnMessage);
this.BeginInvoke(d, new object[] { sender, d });
}
else
{
TheLabel.Text=d.ToString();
}
}
....
}

For example, if there are three events I have to write codes like
above three times. Am I using a wrong scheme? Is there any nicer,
cleaner way? I hope that I could hear some advices from you. Thank you.
 
J

Jon Skeet [C# MVP]

Event handlers for events from an object of another thread than the UI
thread cannot access UI components, as you know. If the object has
many events this precedure is painstaking. Plus the source code gets
longer and dirtier.

As Peter Duniho has pointed out various times, there's little cost in
calling Invoke or BeginInvoke when you don't have to. Now, combine
that fact with the way that often your logic doesn't actually *need*
the sender (or logically always casts) it - and anonymous methods or
lambda expressions. Change the event subscription code to:

ObjectFromAnotherThread.MessageReceived += (sender, d) =>
BeginInvoke(OnMessage(d));

void OnMessage(Data d)
{
TheLabel.Text=d.ToString();
}

Nice and straightforward :)

It's slightly messier in C# 2 with anonymous methods, but still not
too bad.

Jon
 
S

Sin Jeong-hun

As Peter Duniho has pointed out various times, there's little cost in
calling Invoke or BeginInvoke when you don't have to. Now, combine
that fact with the way that often your logic doesn't actually *need*
the sender (or logically always casts) it - and anonymous methods or
lambda expressions. Change the event subscription code to:

ObjectFromAnotherThread.MessageReceived += (sender, d) =>
BeginInvoke(OnMessage(d));

void OnMessage(Data d)
{
     TheLabel.Text=d.ToString();

}

Nice and straightforward :)

It's slightly messier in C# 2 with anonymous methods, but still not
too bad.

Jon

Thank you. Could you please tell me how to write the code above in C#
2.0 syntax? Because I mostly use C# 2.0 (I'ld like to use the latest
version but there are more chances that .NET Framework 2.0 is
installed on the client system than 3.0 is.)
 
M

Marc Gravell

Something like:

ObjectFromAnotherThread.MessageReceived += delegate
(object sender, Data d) {BeginInvoke(OnMessage(d));};

Marc
 
J

Jon Skeet [C# MVP]

Thank you. Could you please tell me how to write the code above in C#
2.0 syntax? Because I mostly use C# 2.0 (I'ld like to use the latest
version but there are more chances that .NET Framework 2.0 is
installed on the client system than 3.0 is.)

Marc has provided the C# 2 syntax, but it's important to understand
that you can still use C# 3 but target .NET 2.0. It's really nice to
have lambda expression goodness (and the rest) but still target the
more widely deployed framework.

See http://csharpindepth.com/Articles/Chapter1/Versions.aspx for more
details.

Jon
 

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

Top