如何等待所有任务完成而不会阻塞UI线程? [英] How to wait until all tasks finished without blocking UI thread?

查看:102
本文介绍了如何等待所有任务完成而不会阻塞UI线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,我在处理任务之前禁用了按钮,并希望在所有任务完成后启用它.

In the following code I disable button before processing tasks and would like to enable it after all tasks are finished.

List<Task> tasks = new List<Task>();
buttonUpdateImage.Enabled = false; // disable button
foreach (OLVListItem item in cellsListView.CheckedItems)
{
    Cell c = (Cell)(item.RowObject);

    var task = Task.Factory.StartNew(() =>
    {
        Process p = new Process();
        ...
        p.Start();
        p.WaitForExit();
    });
    task.ContinueWith(t => c.Status = 0);
    tasks.Add(task);
}

Task.WaitAll(tasks.ToArray());
// enable button here

WaitAll 阻止了UI线程.如何等待所有任务完成然后启用按钮?

WaitAll is blocking the UI thread. How can I wait until all tasks finish and then enable the button?

推荐答案

首先,我将安装现在,使用这个问题的答案,您可以异步注册进程退出,而无需使用 Task.Factory.StartNew :

Now, using the answer to this question, you can asynchronously register for process exit, with no need to use Task.Factory.StartNew:

public static class ProcessExtensions
{
    public static Task RunProcessAsync(this Process process, string fileName)
    {
        if (process == null)
            throw new ArgumentNullException(nameof(process));

        var tcs = new TaskCompletionSource<bool>();
        process.StartInfo = new ProcessStartInfo
        {
            FileName = fileName 
        };

        process.EnableRaisingEvents = true
        process.Exited += (sender, args) =>
        {
            tcs.SetResult(true);
            process.Dispose();
        };

        process.Start();
        return tcs.Task;
    }
}

现在,您可以执行以下操作:

Now, you can do this:

buttonUpdateImage.Enabled = false; // disable button

var tasks = cellsListView.CheckedItems.Cast<OLVListItem>()
                                      .Select(async item => 
{
    Cell cell = (Cell)item.RowObject;

    var process = new Process();
    await process.RunProcessAsync("path");

    cell.Status = 0;
});

await Task.WhenAll(tasks);
buttonUpdateImage.Enabled = true;

这篇关于如何等待所有任务完成而不会阻塞UI线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆