在UI线程上异步调用同步方法

时间:2009-03-10 10:34:30

标签: c# multithreading asynchronous

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

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

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

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

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

有什么建议吗?

5 个答案:

答案 0 :(得分:3)

尝试使用BackgroundWorker类,它的设计完全符合您的需要。

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

答案 1 :(得分:0)

尝试Backgroundworker课程。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

使用event和threadpool

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

当数据到达时,这将调用FunctionToCallWhenDone。你也使用ThreadPool,它应该比创建自己的线程便宜。但是,正如Kurt Schelfthout指出你必须做一些像uielement.Invoke(()=> {some code})这样的东西来改变UI。

答案 4 :(得分:0)

您不需要阻塞或循环,只需将回调方法(委托)作为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;
}