【问题标题】:Calling synchronous methods asynchronously on the UI thread在 UI 线程上异步调用同步方法
【发布时间】:2009-03-10 20:49:30
【问题描述】:

我编写了一个检查 POP3 帐户的类,我希望它在 UI 线程以外的线程上执行。

为此,我选择了异步路由。

为了从 pop3delegate.BeginInvoke(null,null) 获取结果,我需要调用 EndInvoke,但在 UI 线程中执行此操作会导致 UI 无法使用。

我可以使用 IAsyncResult 对象并检查 IsComplete 属性,但这涉及放入一个检查循环,这反过来又锁定了 UI。

我正在寻找一种从 POP3 类中获取完成百分比或某种状态的方法,这反过来会更新 UI 并允许 UI 可用于执行其他任务。我还需要在某个时候调用 EndInvoke 方法,以捕获工作线程上抛出的任何异常。

有什么建议吗?

【问题讨论】:

    标签: c# multithreading asynchronous


    【解决方案1】:

    尝试使用 BackgroundWorker 类,它旨在满足您的需求。

    msdn 上的示例和更多详细信息:http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

    【讨论】:

    • 我已经读过,它似乎是一种基于事件的报告方式,但是,仔细想想,我可以在我的 pop3 类中有事件并将 UI 方法挂钩到它们显示结果。
    【解决方案2】:

    试试Backgroundworker 类。

    【讨论】:

      【解决方案3】:

      使用 BackgroundWorker。它还省去了在 UI 和后台 trheads 之间来回编组数据的麻烦,并且允许进度通知和取消。

      【讨论】:

        【解决方案4】:

        使用事件和线程池

        var asyncResult = pop3delegate.BeginInvoke(null,null);
        ThreadPool.RegisterWaitForSingleObject(
            asyncResult.WaitHandle, FunctionToCallWhenDone, null, TimeSpan.Infinite, true);
        

        这将在数据到达时调用您的 FunctionToCallWhenDone。您还使用 ThreadPool 应该比创建自己的线程便宜。然而,正如 Kurt Schelfthout 所说,您必须执行类似 uielement.Invoke(()=>{some code}) 之类的操作才能更改 UI。

        【讨论】:

          【解决方案5】:

          你不需要阻塞或循环,你可以简单地传递一个回调方法(委托)作为你的 BeginInvoke 调用的第一个参数,这里你可以调用 EndInvoke 进程异常等。

          private delegate int LongRunningTaskHandler();
          static void Main(string[] args) {
              LongRunningTaskHandler handler = LongRunningTask;
              handler.BeginInvoke(MyCallBack, null);
              Console.ReadLine();
          }
          private static void MyCallBack(IAsyncResult ar) {
              var result = (LongRunningTaskHandler)((AsyncResult) ar).AsyncDelegate;
              Console.WriteLine(result.EndInvoke(ar));
          }
          public static int LongRunningTask()
          {
              Thread.Sleep(5000);
              return 42;
          }
          

          【讨论】:

          • 回调方法不会给我一个进度指示器,只是任务完成。我需要定期检查。
          猜你喜欢
          • 2019-04-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多