2015-02-12 39 views
1

你好,我有下面的代碼,創建一個任務。然後設置它開始。 該任務旨在添加對ConcurrentBag列表的響應。 但等待似乎並沒有等待所有的任務完成。但他們被標記爲已完成。列表中只有一個任務。 使用Task.Run時可以正常工作!Task.Start奇怪的行爲

public async void RunT1() 
{   

    DoesNotWork(); 

} 

public async void RunT2() 
{   

    DoesWork(); 

} 

public async void DoesNotWork() 
{ 
    ConcurrentBag<string> concurrentBag = new ConcurrentBag<string>(); 
    List<Task> taskList = new List<Task>(); 

    Task task1 = new Task(async() => 
    { 

     var xml = await LongWorkingMethod(); 
     concurrentBag.Add(xml); 

    }); 

    taskList.Add(task1); 

    taskList[0].Start(); 
    await Task.WhenAll(taskList); 

    if (concurrentBag.Count > 0)//concurrentBag is empty even though the task has finished 
    { 
     Debug.Print("success"); 
    } 
} 

public async void DoesWork() 
{ 
    ConcurrentBag<string> concurrentBag = new ConcurrentBag<string>(); 
    List<Task> taskList = new List<Task>(); 

    Task task1 = Task.Run(async() => 
    { 

     var xml = await LongWorkingMethod(); 
     concurrentBag.Add(xml); 

    }); 

    taskList.Add(task1); 


    await Task.WhenAll(taskList); 

    if (concurrentBag.Count > 0)//concurrentBag is NOT empty 
    { 
     Debug.Print("success"); 
    } 
} 

回答

6

有幾乎沒有理由直接使用Task構造。

在你的情況Task構造不支持async代表(即的,而不是ActionFunc<Task>),當你傳遞一個作爲參數是它視爲async void

這意味着,調用Start「火災和忘記」委託並不能等待它裏面的異步操作才能完成,因爲在沒有Taskawait

var task = new Task(async() => await Task.Delay(1000)); 
task.Start(); 
await task; // completes immediately 

使用Task.Run在你需要運行一個新的Task案件。 Task.Run,正如你看到的,不正確地支持async委託,並等待整個操作完成

var task = Task.Run(async() => await Task.Delay(1000)); 
await task; // completes after 1000 milliseconds 
+0

我想以後2在同一時間運行它們。這是有道理的。但似乎沒有一個選項來處理我的taskList說只使用2線程。它會用完所有的線程,如果我使用Task.Run – lymber 2015-02-12 07:51:53

+1

@lymber將它們添加到列表中,如果你想先準備它們並稍後執行它們,我將只存儲一個'Func '列表,並且當你調用它們時他們開始跑步。 – i3arnon 2015-02-12 07:53:32

+0

是的,但我不希望他們都開始運行。同時運行兩個,等待這兩個運行,然後執行下兩個,直到列表被消耗完。 – lymber 2015-02-12 07:57:43