我想使用来自任务的委托来更新winforms中的进度条。
scheduler = TaskScheduler.FromCurrentSynchronizationContext();
public delegate void NotifyAboutIterationEnd(int iteration);
public event NotifyAboutIterationEnd Notify;
var task = Task.Factory.StartNew(() =>
{
//...
Task.Factory.StartNew(() =>
{
Notify(++index);
}, CancellationToken.None, TaskCreationOptions.None, scheduler);
//...
当我启动这段代码时,我可以命中的最后一个断点符合Notify(++ index); 然后程序冻结,结束了。 如果我将调度程序更改为例如scheduler = TaskScheduler.Current;然后我有一个例外,gui无法从其他线程修改。这意味着委托/事件正常工作。那么为什么它不能在第一种情况下起作用呢?
答案 0 :(得分:1)
这是因为Task.Factory.StartNew()实际上没有启动新任务,而是SCEDULE它。即使主要任务完成,默认的scheduller也可以启动它们。记住任务!=线程。 Thread.Start - allways立即启动线程,Task.Factory.StartNew或Task.Start只计划。您可以在Task.Factory.StartNew()之后使用.Wait()。这将导致等待进度条更新。 但是,我觉得这不是最佳解决方案。解决方案我真的建议如果你的计算花了很多时间我们Task.Factory.Startnew与TaskCreationOptions.LongRunning 和Notify.BeginInvoke用于更新进度条。必须根据Winforms Updating UI Asynchronously Pattern正确实现notify事件的处理程序。 你可以在Winforms Updating UI Asynchronously Pattern - Need to Generalize看一个例子 希望这有帮助!
平行缺乏;)。
答案 1 :(得分:0)
你可以这样做
ProgressBar pb = new ProgressBar();
pb.Maximum = 100;
pb.Dock = DockStyle.Fill;
Controls.Add(pb);
int i = 0, flag = 5;
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
while (i <= 100
{
Task.Factory.StartNew(() =>
{
pb.Value++;
}, System.Threading.CancellationToken.None, TaskCreationOptions.None, uiScheduler);
System.Threading.Thread.SpinWait(50000000); // do work here
i++
}
});