Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多个任务,每个任务完成时更新UI_C#_Wpf_Task - Fatal编程技术网

C# 多个任务,每个任务完成时更新UI

C# 多个任务,每个任务完成时更新UI,c#,wpf,task,C#,Wpf,Task,因此,我有一个后台工作人员,负责执行一系列类似的任务 taskList.Add(Task.Factory.StartNew(Task1)); taskList.Add(Task.Factory.StartNew(Task2)); ... Task.WaitAll(taskList.ToArray()); 它们被放置在一个worker中,这样我就可以在XAML中显示一个加载图标。然后worker.RunWorkerCompleted将删除加载图标,并在所有任务完成后将UI释放给用户 接下来,我想

因此,我有一个
后台工作人员
,负责执行一系列类似的任务

taskList.Add(Task.Factory.StartNew(Task1));
taskList.Add(Task.Factory.StartNew(Task2));
...
Task.WaitAll(taskList.ToArray());
它们被放置在一个worker中,这样我就可以在XAML中显示一个加载图标。然后
worker.RunWorkerCompleted
将删除加载图标,并在所有任务完成后将UI释放给用户

接下来,我想在任务完成时更新加载UI。即,当第一个任务完成时,加载图标下的标签将显示“任务1完成”,依此类推


完成这项工作的最佳方式是什么?我曾想过我可以将任务更改为BackgroundWorkers,然后使用他们的
RunWorkerCompleted
事件来更新UI,但我想知道这是正确/最佳/合理的方法吗?

如果我正确理解了您的问题,您可以使用
ContinueWith
方法并在调用(UI)上启动任务线程:


每个任务都可以通过UI线程的调度程序更新UI:

taskList.Add(Task.Run(() =>
{
    // do lengthy operation

    Application.Current.Dispatcher.Invoke(() =>
    {
        // update UI
    });
}));
然后通过
Task等待所有任务。当所有任务完成时,进行最终的UI更新:

await Task.WhenAll(taskList.ToArray());

// update UI

不需要后台工作人员。

为什么不使用线程呢?根本不需要BGW。如果您正在使用任务,只需在任务完成后等待它们完成工作,而不是创建一个新线程,什么也不做,只是坐在那里等待另一个线程完成其工作。@MarcoSalerno所描述的代码已经在使用大量线程。@MarcoSalerno这只是失去了您的功能,而你什么也得不到。@MarcoSalerno
线程
允许你做什么,TPL不允许你做什么,这与手头的问题无关?为什么?当
async/await
可用时,没有理由这样做。此外,此代码会死锁<代码>任务。WaitAll将阻止UI线程,这意味着没有任务能够更新它。所以没有人会finish@PanagiotisKanavos你错了。如果“没有理由”使用ContinueWith方法,则此方法将被标记为已弃用。等待每个任务将使它们依次运行。而这段代码在后台线程上运行时不会死锁。因此,再多一个线程来处理阻塞代码,这本来是可以避免的。When
等待任务。WhenAll()
本可以避免该问题。至于不推荐的,嗯,是的,这个样式从4.5开始就过时了。甚至还有一个类可以从多个线程报告进度,您不需要“多个线程”。您可以在UI线程上调用ContinueWith方法,只需使用wait Task.WhenAll。为什么会死锁?@mm8
ContinueWith
是一个低级工具。很少有情况下它是有用的,甚至是必要的,但这些情况很少,而且几乎总是涉及到其他更高级别工具的实现(例如,
await
,它在概念上是一个更高级别的工具,可以为您创建连续性,但添加了功能,您的代码没有这些功能就更糟糕)…NET通常不会实际使用过时属性,即使他们使自己的内容过时(看看,比如说,
ArrayList
,任何人都不应该再使用它了)。
await Task.WhenAll(taskList.ToArray());

// update UI