递归任务队列
我想通过队列迭代 - 从队列中取1项,在后台任务中处理它,更新UI,然后取下一个项目,依此类推。问题是第一个项目在后台任务(线程)中处理,但随后的项目在UI线程中处理 - 阻止UI。递归任务队列
有谁知道为什么发生这种情况,以及如何解决这个问题?我的完整测试代码如下。注意:这段代码是为了我的学习和将来的参考 - 不是任何真实的应用程序。
public partial class MainWindow : Window
{
private Queue<int> testQueue = new Queue<int>();
private TaskScheduler uiScheduler;
public MainWindow()
{
InitializeComponent();
this.uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
this.testQueue = new Queue<int>();
this.testQueue.Enqueue(3);
this.testQueue.Enqueue(6);
this.testQueue.Enqueue(7);
this.testQueue.Enqueue(11);
this.testQueue.Enqueue(13);
}
// just a method that takes about 1 second to run on a modern pc
private double SumRootN(int root)
{
double result = 0;
for (int i = 1; i < 10000000; i++)
{
result += Math.Exp(Math.Log(i)/root);
}
return result;
}
private void testQueueButton_Click(object sender, RoutedEventArgs e)
{
this.processQueue();
}
private void processQueue()
{
if (this.testQueue.Count > 0)
{
int root = this.testQueue.Dequeue();
Task<double>.Factory.StartNew(() => SumRootN(root))
.ContinueWith(t =>
{
this.statusText.Text += String.Format("root {0} : {1}\n", root, t.Result);
this.processQueue();
}, uiScheduler);
}
else
{
this.statusText.Text += "Done\n";
}
}
}
感谢您发布一个repro,它允许我进行调试。
Task.Factory.StartNew在调度程序(factoryScheduler ?? currentTaskScheduler ?? threadPoolScheduler)
上运行您的任务。你进入了第二种情况:你的新任务从它的父节点继承调度器。
我注意到你好奇的使用递归调用来模拟一个循环。如果你不喜欢这样,问题消失:
Task<double>.Factory.StartNew(() => SumRootN(root))
.ContinueWith(t =>
{
this.statusText.Text += String.Format("root {0} : {1}\n", root, t.Result);
}, uiScheduler).ContinueWith(t => { this.processQueue(); });
这是因为您正在使用TaskScheduler.FromCurrentSynchronizationContext()
- 您确实知道它的作用是对的吗? (使得它在同一个线程的叫法,在你的情况下,UI上运行)
编辑: USR回答你这是为什么发生的事情,但你也可以做到这一点(把准并行处理):
int root = this.testQueue.Dequeue();
Task<double>.Factory.StartNew(() => SumRootN(root))
.ContinueWith(t =>
{
this.statusText.Text += String.Format("root {0} : {1}\n", root, t.Result);
}, uiScheduler);
this.processQueue();
是的,后续任务并在UI线程,但第一个任务'任务
@ flolim - 更新了答案... –
非常感谢!我错误地假设了。 – flolim
我也是。我调试了这个,因为我无法相信它。 – usr