在C#中异步使用委托

时间:2009-12-09 16:41:44

标签: c# asynchronous delegates

我有以下代表

delegate void UpdateFileDelegate(long maxFileID);

我正在从WinForms应用程序中调用

UpdateFileDelegate FD = new UpdateFileDelegate(ClassInstance.UpdateFile);
FD.BeginInvoke(longIDNumber,null,null);

它以异步方式运行,但我的问题是如何判断Method何时完成执行,以便让最终用户知道?

更新: 感谢以下建议,以下代码可以解决问题。 此article有助于我了解我的代码实际上在做什么。

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!");
    }

2 个答案:

答案 0 :(得分:7)

请参阅Calling Synchronous Methods Asynchronously

BeginInvoke将返回IAsyncResult,这可以通过多种不同方式了解何时完成,例如使用其AsyncWaitHandle.WaitOne()方法。这取决于你在此期间做了什么。

或者您可以将回调方法的委托传递给BeginInvoke。这可以说是最强大的策略,但有时候是过度杀伤。

答案 1 :(得分:7)

在返回的IAsyncResult引用上调用EndInvoke非常重要。这是查明委托目标是否完成执行而没有任何异常的唯一方法。如果不这样做,这样的异常将落入bit-bucket,你的程序将无法正常执行。您可以在调用BeginInvoke()的同一线程上调用EndInvoke,也可以在回调中执行。在同一个线程上调用它很少有用,你几乎总是会失去异步执行的好处。一些示例代码演示了这两个并强调了异常处理:

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);
    }
  }
}

如果您不希望代码抛出异常,则不应在完成回调中使用try块。这可以确保程序在程序结束时终止。