开发者

Using Delegates in C# Asynchronously

I have the following delegate

delegate void UpdateFileDelegate(long maxFileID);

That I am calling from a WinForms app like so

UpdateFileDelegate FD = new UpdateFileDelegate(ClassInstance.UpdateFile);
FD.BeginInvoke(longIDNumber,null,null);
开发者_如何学运维

It runs asynchronously but the question I have is how can I tell when the Method is done executing so I can let the end user know?

Update: Thanks to the recommendations below the following code does the trick. Also this article was helpful in getting me to understand what my code is actually doing.

delegate void UpdateFileDelegate(long maxFileID);
UpdateFileDelegate FB = new UpdateFileDelegate(ClassInstance.UpdateFile);
AsyncCallback callback = new AsyncCallback(this.CallBackMethod);
IAsyncResult result = FB.BeginInvoke(longIDNumber);

private void CallBackMethod(IAsyncResult result)
    {
     AsyncResult delegateResult = (AsyncResult)result;

     UpdateFileDelegate fd = (UpdateFileDelegate)delegateResult.AsyncDelegate;
     fd.EndInvoke(result);
     MessageBox.Show("All Done!");
    }


See Calling Synchronous Methods Asynchronously

The BeginInvoke will return an IAsyncResult, which enables a number of different ways to be aware of when it is done, such as using its AsyncWaitHandle.WaitOne() method. It depends on what you are doing in the meantime.

Or you can pass a delegate for a callback method to BeginInvoke. This is arguably the most powerful strategy, but sometimes is overkill.


Calling EndInvoke on the returned IAsyncResult reference is very important. It is the only way to find out if the delegate target finished executing without any exceptions. If you don't, such an exception will fall into the bit-bucket and your program will silently fail to execute properly. You can call EndInvoke either on the same thread that called BeginInvoke() or you can do it in a callback. Calling it on the same thread rarely is useful, you'd almost always lose the benefits of asynchronous execution. Some sample code that demonstrates both and emphasizes the exception handling:

using System;
using System.Runtime.Remoting.Messaging;

class Program {
  static void Main(string[] args) {
    new Program().Run();
    Console.ReadLine();
  }
  void Run() {
    Action example = new Action(threaded);
    IAsyncResult ia = example.BeginInvoke(new AsyncCallback(completed), null);
    // Option #1:
    /*
    ia.AsyncWaitHandle.WaitOne();
    try {
      example.EndInvoke(ia);
    }
    catch (ApplicationException ex) {
      Console.WriteLine(ex.Message);
    }
    */
  }

  void threaded() {
    throw new ApplicationException("Kaboom");
  }

  void completed(IAsyncResult ar) {
    // Option #2:
    Action example = (ar as AsyncResult).AsyncDelegate as Action;
    try {
      example.EndInvoke(ar);
    }
    catch (ApplicationException ex) {
      Console.WriteLine(ex.Message);
    }
  }
}

You should not use a try block in the completion callback if you don't expect the code to throw exceptions. This ensures your program terminates when it does.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜