簡體   English   中英

C#在循環內等待任務

[英]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並在Taskawait ,不要使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM