3

I was using code like this:

handler.Invoke(sender, e);

But the problem with that code is that it is synchronous and all it really does is update the GUI. It is not necessary for the server to wait for it to complete so it should be made asynchronous.

I don't really want to use BeginInvoke and EndInvoke because a callback method is not necessary in this case.

Is this a suitable alternative?

Task.Factory.StartNew(() => handler.Invoke(sender, e));
Taryn
  • 242,637
  • 56
  • 362
  • 405
Ryan Peschel
  • 11,087
  • 19
  • 74
  • 136
  • Everything you are thinking of doesn't actually work. If you want to run code on the UI thread then use Dispatcher.Invoke or Control.BeginInvoke(), whatever ui library you picked. – Hans Passant Oct 02 '11 at 00:03
  • @Hans Passant: I am using Control.BeginInvoke in the actual event handler. I apologize; I should have specified the originally posted code was for an extension method for the `EventHandler` class to raise an event asynchronously. – Ryan Peschel Oct 02 '11 at 00:15

3 Answers3

0

The way you did it is fine, another way to do this that works on .NET 3.5 is using the ThreadPool class instead

ThreadPool.QueueUserWorkItem(new WaitCallback((a) => handler.Invoke(sender, e)))

Also if handler happens to be a derived from control, you are allowed to call BeginInvoke without a corresponding EndInvoke.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
0

Calls to GUI are special in that they must always be done from the GUI thread. In your own words, handler.Invoke(sender, e) "updates the GUI", yet it is (probably) not executed from the GUI thread, so it not OK in its current form.

In WinForms, you'll need to wrap your task delegate into Control.Invoke (or forget about tasks and just use Control.BeginInvoke).

If WPF, you can wrap your task delegate into Dispatcher.Invoke (or just use Dispatcher.BeginInvoke without a task).

Branko Dimitrijevic
  • 50,809
  • 10
  • 93
  • 167
  • I am already doing that within the event handler. I was wondering if I should also invoke the event handler asynchronously and if so, if the originally posted code was the proper way to do so. – Ryan Peschel Oct 02 '11 at 00:22
-1

I'm not familiar with C# 4's Task class, but I know BeginInvoke works just fine without EndInvoke. I sometimes write code like this:

handler.BeginInvoke(sender, e, null, null);

Edit: I was mistaken. While EndInvoke is not necessary to cause the code to execute on a new thread, the documentation clearly states that EndInvoke is important.

Joshua Tacoma
  • 408
  • 5
  • 13
  • 2
    With this code, any exception thrown by `handler` is silently ignored. So if you want to do this, you better know what you are doing. – svick Oct 01 '11 at 23:26
  • @Joshua: Yes but BeginInvoke calls must, as stated by the documentation, end with an EndInvoke call (which would normally be placed in the callback). – Ryan Peschel Oct 01 '11 at 23:26
  • @svick: good point. Still, Task.Factory.StartNew must have the same problem since exceptions can only be caught in the thread that throws them. You have to know what you're doing either way. – Joshua Tacoma Oct 01 '11 at 23:32
  • @RyanPeschel: despite what the documentation says, EndInvoke is not necessary if all you want to do is execute some code in a new thread. – Joshua Tacoma Oct 01 '11 at 23:34
  • Ok, ok, I just reviewed the documentation and they certainly emphasize the use of EndInvoke, calling it "important". Looks like I'm going to have to revise some of my own code... – Joshua Tacoma Oct 01 '11 at 23:44
  • 1
    @Joshua: Check out [this](http://stackoverflow.com/questions/532722/is-endinvoke-optional-sort-of-optional-or-definitely-not-optional) and [this](http://stackoverflow.com/questions/4585042/is-delegate-endinvoke-really-necessary) if you have not already. – Ryan Peschel Oct 01 '11 at 23:45
  • @RyanPeschel: thank you. One of your links mentions ThreadPool.QueueUserWorkItem, which looks like exactly what I should have been using in my own code. – Joshua Tacoma Oct 01 '11 at 23:56