首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >递归任务队列

递归任务队列
EN

Stack Overflow用户
提问于 2012-06-25 06:15:41
回答 2查看 3.3K关注 0票数 3

我正在尝试迭代队列-从队列中获取1个条目,在后台任务中处理它,更新UI,然后获取下一个条目,依此类推。问题是第一个项目是在后台任务(线程)中处理的,而随后的项目是在UI线程中处理的-阻塞了UI。

有谁知道为什么会发生这种情况,以及如何解决这个问题?我的完整测试代码如下。注意:这段代码仅供我学习和将来参考-不是任何实际的应用程序。

代码语言:javascript
复制
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";
        }
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-25 06:37:09

谢谢你贴了一张复制品,让我可以调试。

Task.Factory.StartNew在调度程序(factoryScheduler ?? currentTaskScheduler ?? threadPoolScheduler)上运行您的任务。您进入了情况2:您的新任务从其父任务继承调度程序。

我注意到你奇怪地使用递归调用来模拟循环。如果你这样做,问题就会消失:

代码语言:javascript
复制
         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(); });
票数 3
EN

Stack Overflow用户

发布于 2012-06-25 06:22:50

那是因为你使用的是TaskScheduler.FromCurrentSynchronizationContext() --你知道它是做什么的,对吧?(使其在调用的同一线程上运行,在本例中为UI)

编辑:用户回答了为什么会发生这种情况,但您也可以这样做(对于准并行处理):

代码语言:javascript
复制
    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();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11181640

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档