C# 为什么在UI线程上调用启动新任务
为什么在UI线程上调用C# 为什么在UI线程上调用启动新任务,c#,.net,multithreading,task-parallel-library,C#,.net,Multithreading,Task Parallel Library,为什么在UI线程上调用t。我知道我针对test创建了一个continuationTask,该任务在UI线程上被正确调用,但我随后开始运行一个新任务。现在我知道我可以通过指定TaskScheduler.Default作为针对t.Start的重载方法来解决这个问题,但是为什么要在ui线程上启动新的Task呢?不要使用Task.Start方法。另外,如果您想延迟一项任务,请使用task.delay如下: Task t = new Task(() => { //I would expect
t
。我知道我针对test
创建了一个continuationTask
,该任务在UI线程上被正确调用,但我随后开始运行一个新任务。现在我知道我可以通过指定TaskScheduler.Default
作为针对t.Start
的重载方法来解决这个问题,但是为什么要在ui线程上启动新的Task
呢?不要使用Task.Start
方法。另外,如果您想延迟一项任务,请使用task.delay
如下:
Task t = new Task(() =>
{
//I would expect this to be on a worker thread, but it's not!
Thread.Sleep(1000);
});
Task test = new Task(() =>
{
Thread.Sleep(1000);
});
test.ContinueWith(x =>
{
//Do some UI Updates here, but also start another Task running.
t.Start();
}, TaskScheduler.FromCurrentSynchronizationContext());
test.Start();
但是为什么要在ui线程上启动一个新的任务
因为除非另有规定,否则在任务上调用Start
会在当前TaskScheduler
上调度任务,在您的情况下,该任务只是UI线程的SynchronizationContext
上的一个门面,该线程是使用TaskScheduler.FromCurrentSynchronizationContext()
创建的
启动任务
,将其调度到当前的任务调度程序
从
如果希望将该任务安排在与当前任务不同的TaskScheduler
上,可以将其作为参数传递:
Task.Delay(TimeSpan.FromSeconds(1)) //Wait 1 second
.ContinueWith(t => DoSomeUIWork(), TaskScheduler.FromCurrentSynchronizationContext()) //execute something on the UI thread
.ContinueWith(t => DoSomeBackgroundWork()); //Then do some background work
注意:使用
Task.Start
是解决此问题的最佳方案,这几乎是不可能的。您可能应该重新考虑这条途径。这应该是一条评论,而不是一个答案,StartNew也会有同样的行为。但这将立即启动任务运行,这不是我想要的行为。有关进一步阅读,请参阅Stephen Cleary的博文“”,具体是“为什么不使用task.Factory.StartNew”一节。它讨论的是Task.Factory.StartNew
而不是Task.Start
,但基本问题(在ContinueWith
中为当前任务计划程序安排任务)是相同的。我仍然有点困惑。我在哪一点上更改了TaskScheduler?我告诉继续在UI线程上运行。但是我从来没有告诉t
在UI线程上运行。@William您在用TaskScheduler.FromCurrentSynchronizationContext
创建的TaskScheduler
上安排继续。此计划程序是继续运行时的当前计划程序。因此,当您调用Start
TaskScheduler时,Current
是您将任务发布到UI线程的特殊调度程序。这很有意义。但是currentSynchronizationContext的方法从来没有建议(仅从它的名称)它应该改变任何状态,但我想它确实改变了。谢谢你answer@William没有。。没有。“更改状态”是指您明确地在特定的任务调度器上调度任务。当你这么做的时候。。任务将在该计划程序上运行,该计划程序将是当前计划程序,并将存储在TaskScheduler.current
。一般提示:没有理由自己使用任务构造函数。
t.Start(TaskScheduler.Defualt);