在Task.ContinueWith中启动新线程

时间:2015-02-14 16:36:10

标签: c# wpf multithreading

我正在构建一个WPF应用程序,它需要job1在后台运行;当job1结束时,它使用Task.ContinueWith切换回UI线程,并根据job1的结果(在我的情况下,启动另一个弹出窗口)对UI进行更改,并在后台启动job2。

问题在于,虽然job1在一个单独的线程中运行,但job2在UI线程中运行(它阻止了popup2)。也许是因为job2是在task1的ContinueWith块内启动的?但为什么?它第一次工作,为什么不第二次?如何解决这个问题?

提前致谢!

enterPop(PopupTypes.popup1);
var task1 = new Task(() => job1()); //task runs in another thread
task1.ContinueWith(previousTask =>
    {   
    //**back in UI thread**
    //check result of job 1, start another popup in UI
    exitPopup();
    enterPop(PopupTypes.popup2);
    //**SUPPOSEDLY** starts another background thread for task 2
    var task2 = new Task(()=> job2());
    task2.ContinueWith(previousTask =>{
        //do task in UI thread...
    },TaskScheduler.FromCurrentSynchronizationContext()); 
    task2.Start();            
  }, TaskScheduler.FromCurrentSynchronizationContext());
task.Start();

2 个答案:

答案 0 :(得分:2)

我不清楚enterPop()exitPopup()方法应该做什么,因为代码示例缺少详细信息。也许他们在GUI中显示某种窗口?还不清楚“作业1的检查结果”部分,“在UI线程中执行任务”等中存在哪些代码。

如果没有这些细节,就无法知道代码实际上在做什么。

无论如何,汉斯的建议是正确的。从不完整的代码示例中可以清楚地看到为什么你会得到你所看到的行为(就此而言,我并不完全清楚你所看到的行为)。但是,如果您使用更常见的async / await模式编写代码,它可能会正常工作:

enterPop(PopupTypes.popup1);
await Task.Run(() => job1()); //task runs in another thread
//**back in UI thread**
//check result of job 1, start another popup in UI
exitPopup();
enterPop(PopupTypes.popup2);
// starts another background thread for task 2
await Task.Run(()=> job2());
exitPopup();
//do task in UI thread...

对于奖励积分,让job1()job2()方法返回您检查的结果(根据您的代码中的推荐),并使用var result = await Task.Run(() => job1());之类的方法来检索值(而不是你现在使用的任何机制。)

答案 1 :(得分:0)

在某些情况下,TaskScheduler可能决定在当前线程中执行Task,例如通过c#:

阅读Jeffrey Richter的书CLR中的以下示例
  

当线程调用Wait方法时,系统会检查是否   线程正在等待的任务已开始执行。如果它   有,然后调用Wait的线程将阻塞,直到任务有   完成运行。但是,如果任务还没有开始执行,那么   系统可以(取决于TaskScheduler)执行任务   调用Wait的线程。如果发生这种情况,那么线程调用   等待不阻止;它执行任务并立即返回

我相信你的逻辑会发生类似的事情。 TaskScheduler只跟随您的任务队列并决定同步执行它。最简单的方法是在默认调度程序

中启动task2
task2.Start(TaskScheduler.Default);