[英]c# wait for a task inside a loop
我通過以下方式在Windows窗體應用程序中使用TPL:
foreach (var item in items)
{
task = Task<object>.Factory.StartNew (() => doWork());
task.Wait();
//update the UI using the result
}
我正在等待任務完成,因為我需要處理列表中的每個項目,但是正如您想象的那樣,這會導致UI線程鎖定(UI凍結)。
我想知道如何以不鎖定UI線程的方式實現此功能。
更新 :我正在使用.NET Framework 4.5
謝謝。
PS DoWork()是一項長期運行的操作。
使事件處理程序async
,並在代表線程池操作的任務上調用await
。 這將導致事件處理程序放棄對UI線程的控制,直到任務完成,然后繼續更新UI並開始下一個任務。
private async void MyButton_Click(object sender, EventArgs e)
{
foreach (var item in items)
{
// assuming C# 5 closure semantics
await Task.Run(() => doWork(item));
// update the UI using the result
}
}
上面的方法假定您要順序運行任務。 如果要並行啟動它們並按完成順序處理結果,則可以使用:
private async void MyButton_Click(object sender, EventArgs e)
{
var tasks = items.Select(item => Task.Run(() => doWork(item))).ToList();
while (tasks.Any())
{
var task = await Task.WhenAny(tasks);
tasks.Remove(task);
var result = await task;
// update the UI using the result
}
}
您可以通過以下兩種方式進行處理。
一種可能不是在線程池線程上執行列表中的每個項目,而是將Task
的整個foreach循環排隊,然后在完成時更新結果。
public async void SoneEventHandler(object sender, EventArgs e)
{
var result = await Task.Run(() => items.Select(item => DoWork()).ToList());
foreach (var item in items)
{
// Update UI
}
}
如果您仍然想處理線程池威脅中的每個項目,請使用Task.Run
並在Task
上await
,不要使用Task.Wait()
進行Task.Wait()
:
public async void SoneEventHandler(object sender, EventArgs e)
{
foreach (var item in items)
{
var result = await Task.Run(() => DoWork());
// Update UI
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.