2013-02-10 246 views
6

我有一個循環創建多個任務,如下所示。 隨着每項任務的完成,我如何更新屏幕(添加一行新增一行數據的文本框)?任務完成

如何檢測所有任務何時完成?

C#代碼

for (int i = 0; i < int.Parse(radTextBoxFloodRequests.Text); i++) 
{ 
     int x = i; 
     // Create a task and supply a user delegate by using a lambda expression. 
     var taskA = new Task(() => TaskRequest(int.Parse(radTextBoxFirstNumber.Text), int.Parse(radTextBoxSecondNumber.Text), int.Parse(radTextBoxFloodDelay.Text), x)); 
     // Start the task. 
     taskA.Start(); 
} 


private void TaskRequest(int number1, int number2, int delay, int count) 
{ 
     // Some long running method 
} 
+1

您想在所有任務完成時獲得觸發器嗎? – bas 2013-02-10 18:55:47

+0

是的,並且每個任務也完成 – user1438082 2013-02-10 20:08:18

+1

是Parallel.For還是Parallel.ForEach爲您提供了一個解決方案?很難真正理解你在找什麼。 – bas 2013-02-10 20:17:47

回答

13

您可以使用ContinueWith()

「創建一個執行異步目標任務完成時延續。」 - MSDN

Task t = new Task(() => Console.WriteLine("")).ContinueWith(task => Console.Writeline("Continue With"), 
                  TaskScheduler.FromCurrentSynchronizationContext()); 
+4

如果您要更新UI,您需要添加參數TaskScheduler.FromCurrentSynchronizationContext,您可能位於不同的線程上。 – Jesse 2013-02-10 18:56:02

+0

我如何把這個放入我的代碼? – user1438082 2013-02-10 20:30:33

+0

在最後一個括號之前加上「,TaskScheduler.FromCurrentSynchronizationContext」 – Jesse 2013-02-11 03:57:17

1

我建議你使用的3個簡單的構造組合:

  • 簡單int numActiveTasks,就是增加與InterlockedIncrement(ref numActiveTasks)上創建任務,即立即taskA.Start()之前和InterlockedDecrement(ref numActiveTasks)遞減在任務結束時,即在功能TaskRequest(...)
  • a ManualResetEvent的末尾,即在任務啓動之前復位並暗示在任務結束計數器減少
  • 一個線程,即WaitOne() S於該ManualResetEvent,然後讀取numActiveTasks

這給你

  • notfication完成單個任務的
  • 完成所有任務的通知(numActiveTasks < = 0)

這樣做的主要優點在於,您對通知發生在哪個線程有良好的信譽。

+0

嗨,你能提供一些代碼來說明這是怎麼完成的嗎? – user1438082 2013-02-10 20:25:20

1

您是在查找Parallel.ForEach()

[Test] 
    public void ParallelTasks() 
    { 
     var strings = new List<string> {"task1", "task2", "task3"}; 

     Parallel.ForEach(strings, str => Console.WriteLine(str + "is done")); 

     // All your parallel tasks are executed now 
    } 
1

在用戶12345678的答案上展開,你可以做類似下面的事情。

private void RunTasks() 
    { 
     Dictionary<string, string> dict = new Dictionary<string, string>(); 

     List<Task> tasks = new List<Task>(); 
     foreach (KeyValuePair<string,string> kvp in dict) 
     { 
      Console.WriteLine("Executing task " + kvp.Key + " ..."); 
      Task t = new Task(() => MyMethod(kvp.Key, kvp.Value)); 
      tasks.Add(t); 
      t.Start(); 
      t.ContinueWith(task => Console.WriteLine(kvp.Key + " completed")); 

     } 

     Console.WriteLine("Waiting tasks to complete..."); 
     Task.WaitAll(tasks.ToArray()); 
     Console.WriteLine("All tasks completed..."); 
    } 

    private void MyMethod(string arg1, string arg2) 
    { 

    }