2012-02-20 20 views
3

在我的申請,我曾經沿着異步操作的字符串,其在功能通過這樣的創造:只有當所有的異步操作完成後,我如何才能讓我的應用程序繼續運行?

public void LotsOfAsync() 
{ 
    DoAsync1(()=> { DoAsync2(()=> { doAsync3(()=> { finalAction();}) }) }); 
} 

不過,現在我已經感動了很多的異步操作成單獨的類和對象,但我想要的相同的結果。主要是我已經將這些異步操作轉移到了成爲集合一部分的類中。

我想我的新的代碼看起來像這樣:

public void lotsOfAsync() 
{ 
    DoAsync1(); 
    for each (MyClass in Async1List) 
    { 
      MyClass.DoAsyn2(); 
     } 
    if (allAsyncOperationsAreComplete) 
    { 
     FinalAction(); 
    } 
} 

我需要什麼樣的事情要做,要得到這個工作?謝謝。


使用低於任務應答,東西似乎仍然缺乏。即使將所有內容都投入到BackgroundWorker後,該程序也不會繼續。

回答

4

您可以使用Task<T>(使用Task Parallel Library for Silverlight) - 這樣的事情也許:

List<Task> tasks = new List<Task>(); 

Task.Factory.StartNew(() => DoAsync1()).ContinueWith(_ => 
{ 
    foreach (MyClass myClass in Async1List) 
    { 
     tasks.Add(Task.Factory.StartNew(() => myClass.DoSomething())); 
    } 
    Task.WaitAll(tasks.ToArray()); 
    FinalAction(); 
}); 
+0

謝謝,myClass.DoSomething()必須返回任何特殊的東西來工作嗎? – Bob 2012-02-20 14:44:28

+0

不,事實上它返回的只是在上面的例子中被忽略 – BrokenGlass 2012-02-20 14:46:09

+1

看起來Windows Phone 7上不存在任務:( – Bob 2012-02-20 14:56:11

2

我不熟悉wp7,但你可以使用計數器作爲靜態字段,並檢查它是否等於0在最後的行動。

每個MyClass.DoAsyn2()都應該觸發一個事件或任何其他代碼來表示它已完成。

另一種選擇是將所有異步移動到任務,並呼籲Task.WaitAll

http://msdn.microsoft.com/en-us/library/dd270695.aspx

+0

確定這是不是我的小費,甚至更好,它幾乎推遲已經實施並準備使用。 – Tobias 2012-02-20 13:18:56

+0

這是正確的答案,但它並沒有幫助我理解如何解決這些事件。如果你解釋這些部分,我可以接受它。 – Bob 2012-02-21 13:11:42

1

你吃過看看在.Net 4的CountdownEvent?這是一個信號結構,其中一個線程將被阻塞,並且只有在其他線程完成並在倒計數事件上調用set時纔會繼續。在構造上的線程調用Wait將繼續之前,使用需要的信號數量初始化它。例如: -

CountdownEvent countdown = new CountdownEvent(3); 

只會讓線程調用Wait進行一次3其他線程呼籲Signal

所以,你的例子或許會是這個樣子:

public void lotsOfAsync()  
{ 
    Int32 numberOfAsyncProcesses = Async1List.Length + 1;   
    CountdownEvent countdown = new CountdownEvent (numberOfAsyncProcesses); 

    DoAsync1(countdown); // call countdown.signal() in the async method once complete. 

    for each (MyClass in Async1List)   
    { 
     // call countdown.signal() in the async method once complete. 
     MyClass.DoAsyn2(countdown);   
    } 

    if(countDown.Wait(TimeSpan.FromSeconds(3)) 
    {    
     FinalAction();  
    } 
} 

我還添加了超時,此時調用線程將在3秒後如果未能獲得所有處理線程的響應解除。在這種情況下,最終的操作將不會執行。

你可以,如果你的目標不是.NET 4

有一個很好的例子here也與監視器/脈衝重現此。希望這可以幫助!

+0

你知道windows phone sdk是否支持.Net 4?我嘗試過使用await和異步之前,但得到錯誤,關鍵字無法識別。 – Bob 2012-02-20 14:45:25

+1

但是,不幸的是,您可以自己實現相同的功能 - 請參閱:http://stackoverflow.com/questions/8879870/syncronizing-actions-in-silverlight – Jeb 2012-02-20 16:05:12

1

看完所有以前的答案後,我無法解決我的問題。

相反,我需要做的是在我的類中創建自定義事件,這些事件在成功完成異步任務時觸發。

被證明是最有用的給我來完成,這是該網站:http://www.marten-online.com/csharp/simple-custom-event-handling.html

我的最終代碼看起來是這樣的:

public void lotsOfAsync() 
{ 
    DoAsync1(); 
    for each (MyClass in Async1List) 
    {  
      MyClass.PropertyChange += new MyClass.PropertyChangeHandler(Async2Complete); 
      MyClass.DoAsyn2(); 
     } 
} 

public void Async2Complete(object sender, PropertyChangeEventArgs data) 
     { 
      if (data.PropertyName == "AsyncComplete") 
      { 
       totalAsyncCompleted++; 
       if (totalAsyncCompleted >= Async1List.Count) 
       { 
        FinalAction(); 
       } 
      } 
     } 
+0

注意:我會使用Interlocked.Increment(ref totalAsyncCompleted)since一個增量不是一個原子操作(一個讀操作後跟一個修改,然後是寫指令,這些操作可能被預先佔用)。 – Jeb 2012-02-21 19:08:23

+0

@JohnParr謝謝 – Bob 2012-02-21 20:26:21

相關問題