【问题标题】:Task.ContinueWith with BeginInvoke not working as expected带有 BeginInvoke 的 Task.ContinueWith 未按预期工作
【发布时间】:2016-01-04 18:51:32
【问题描述】:

考虑以下代码:

Task task1;
Task task2;
private void button1_Click(object sender, EventArgs e)
{
    task1 = Task.Run(() =>
    {
        for (int i = 0; i < 100000; i++)
        {
            BeginInvoke(new Action<int>((int n) =>
            {
                listView1.Items.Add(n.ToString());
            }), i);
        }
    });            
    task2 = task1.ContinueWith(t =>
    {
        MessageBox.Show("Why isn't this reached");
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

private void button2_Click(object sender, EventArgs e)
{
    MessageBox.Show(String.Format("task1 status:{0}\r\ntask2 status:{1}", task1.Status, task2.Status));
}

如果我在 Windows 8 .NET Framework 4.5.2 上运行它,当我单击 button2 时会得到以下输出:

task1 状态:RanToCompletion

task2 状态:WaitingToRun

即使我使用了 ContinueWith,这怎么可能?

我知道 BeginInvoke 只是将委托排入队列以执行,如果我使用 Invoke 它工作得很好。这是一个错误还是干扰了 BeginInvoke?有任何想法吗?提前致谢。

【问题讨论】:

  • 您正在淹没消息队列,也许您需要等待更长的时间才能点击按钮 2,直到您在 listblox 中看到 100000 时才单击它。那它有用吗?
  • 不,它与此无关,task2 永远不会被调用。但是,如果我使用较慢的上限,因为我喜欢 100 而不是 100000,它会被调用就好了。难道是windows消息泵超载了?但是它确实添加了所有 100000 个项目,这很奇怪..

标签: c# task


【解决方案1】:

我没有主要来源,但this post 指出消息队列的记录限制为 10,000 条(Hans Passant 是该站点上 Windows 表单方面最专家之一,因此我相信他的话,即限制存在)。

因为您将 100,000 条记录放在那里,所以它要么将您的 ContinueWith 推离堆栈,要么一开始就永远不会被添加到那里(我不确定是哪个)

【讨论】:

  • 所有项目都添加了,但是如果要禁止记录,那么它们怎么能全部执行呢?
  • 消息队列的限制是10000,我看到了,但是通过BeginInvoke添加的所有项目无论如何都添加了,所以消息队列似乎不是限制因素。您确定 Task.FromCurrentSyncronizationContext 是通过 Windows 消息实现的吗?谢谢你的另一篇文章,会看看它。
  • 我想我知道,有两个队列,一个调用队列和一个消息队列。对 BeginInvoke 的每次调用都会将委托添加到调用队列,并将“处理调用队列”消息添加到消息队列。调用队列没有限制,消息队列有 10,000 个限制。所以发生的事情是你用 10,000 条“处理”消息填充消息队列,而你的 continue with 永远没有机会进入(或被推离,仍然不确定会发生什么)消息队列。在第一个“进程”完成后,调用队列为空,但它仍会通过其他 9,999 条进程消息。
  • 是的,我确信 Task.FromCurrentSyncronizationContext 使用 Windows 消息,这是在 WinForms 的 UI 线程上排队运行的唯一方法。
  • 我同意单独的队列,但是如果每次对 BeginInvoke 的调用都会向调用队列添加一个委托并将“进程调用”消息添加到消息队列,那么不会超过 10000 个项目补充会有吗? BeginInvoke 不是同步的,因为它只是将委托添加到一个/多个队列中,但我不明白如何添加所有 100 000 个项目,但 ContinueWith 以某种方式失败。
猜你喜欢
  • 2014-10-20
  • 2021-06-29
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
  • 2018-05-03
  • 2018-07-25
  • 1970-01-01
  • 2021-11-13
相关资源
最近更新 更多