2015-09-28 43 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線程開始,它應該已經正常工作 –