2015-09-28 95 views
2

async operation的结果能否返回到启动它的线程(即在原始线程中调用AsyncCallback)?将异步操作结果返回到原始线程

下面是一个例子

void Main(string[] args) 
    { 

     Func<bool> action =() => 
     { 
      Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ": Running"); 
      return true; 
     }; 

     AsyncCallback onComplete = (r) => 
     { 
      bool result = action.EndInvoke(r); 
      Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ": Completed"); 
     }; 

     Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ": Main"); 
     IAsyncResult iar = action.BeginInvoke(onComplete, null); 
    } 

它的输出是一样的东西:

5: Main 
6: Running 
6: Completed 

我想达成什么是onComplete回调在主线程(如已完成,并主要将执行。在这个例子中印有相同的线程ID)

(我知道这可以通过BackgroundWorker来实现,即它是RunWorkerCompleted事件在原始线程中触发,因此在后台线程中调用的函数的返回值可以返回到原始线程)

+0

那么为什么不使用BackgroundWorker呢?它不是密封的,所以你甚至可以从它中派生出来添加你自己的魔法。 – Nebula

+0

交谈中,您可能可以发送对主线程的引用以及任务并跨线程访问它。但要测试并确保它始终有效? Brrr ... – Nebula

+2

@Nebula对'Thread'的访问不允许你将* work *推送到一个线程;为此,您需要某种工作队列机制。 –

回答

5

这在很大程度上是您选择使用的SynchronizationContextTaskScheduler实现的问题。在许多UI框架(winforms,WPF等)的情况下,是的:如果你开始在UI线程上工作,回调可能发生在UI线程上 - 但这不适用于一般情况下,其中一个ThreadPool线程更有可能获胜。最终,你不能简单地强制回到特定的线程,除非线程是设计检查一些工作队列,当他们到达时出队/执行数据包(这正是UI框架所做的) 。

+0

所以:只要使用适合您账单的任何线程类型?或者这太粗糙了? – Nebula

+0

假设这是为WPF应用程序猜测我可以做一些像'action.BeginInvoke((r)=> Dispatcher.BeginInvoke(onComplete(r)),null)'即。当动作在辅助线程上完成时,它会在UI线程上排队'onComplete'回调?但是想知道是否还有其他的方式可以完成(没有显式的Dispatcher调用) - 就像在'Timer'中设置'SynchronizingObject'不为null'一样。 – ubi

+0

@ubi如果您从UI线程开始,它应该已经正常工作 –