【问题标题】:Task.Factory.StartNew invoked on UI thread anyhow无论如何在 UI 线程上调用 Task.Factory.StartNew
【发布时间】:2013-07-18 00:17:18
【问题描述】:

至少从我的角度来看,我必须处理一个奇怪的问题。我使用一个任务等到一个变量得到一个特定的值,然后再次在 ui 线程上运行 Continue 部分。

现在的问题是,在我调用 StartNew() 之前,在调用内部 ManagedThreadId 是相同的,它会冻结我的 UI。

这是我的代码:

// ManagedThreadId here
Task.Factory.StartNew(() => 
{
    // and here are the same.
    while (isClosing)
    {
        Thread.Sleep(50);
    }
}).ContinueWith((finishedTask) => 
{
    if (currentContainer != null)
    {
        window = currentContainer;
    }
    else
    {
         window = CreateBallonWindow();
         window.Show();
    }

    window.Activate();
}, TaskScheduler.FromCurrentSynchronizationContext());

想法?

感谢克里斯托夫

编辑:

对我来说最有趣的是为什么会发生这种情况而不是如何解决这个问题。 我想了解那里发生了什么......

【问题讨论】:

  • 是的,但我不想在每次关闭窗口时都引发操作。我只是想确保在我打开一个新的时它已关闭。此外,对我来说如何解决这个问题更有趣的是要了解为什么两者都在同一个线程上执行。对不起,如果这不是我的问题。
  • 我已经整理了一个示例应用程序,它对我来说运行良好,但是,当您查询托管 ID 时,您是否将它放入了一个带有闭包的变量中?我的 UI 线程 ID 为 9,我的内部线程 ID(来自 ThreadPool)为 10。
  • Task.Factory.StartNew 不保证会生成新的线程检查 This answer 以获取一些详细信息以及其中的前 2 个 cmets。您也可以尝试将 TaskCreationOptions.LongRunning 指定为该链接答案提及的第四条评论,以强制为任务生成一个新线程
  • @Viv 如果没有提供,它不使用默认的TaskScheduler 吗?对我来说这是ThreadPool(根据我的调试器)。
  • 检查 TaskScheduler.FromCurrentSynchronizationContext() 在运行时返回的内容。如果您已经线程池中,则 threadid 可能保持不变。

标签: c# wpf multithreading task


【解决方案1】:

谢谢大家的指点,

我终于认为我明白了。这里的问题是 TaskScheduler.Current 是调用 StartNew() 时使用的默认调度程序。而且这在使用 TaskScheduler.SynchronizationContext() 时不是很好的组合。

这里的情况是我(间接地)在任务调度器描述的调度程序中使用了 StartNew()。因此默认调度程序是包含 ui 线程的调度程序 --> 在 ui 线程上调用了新任务。

特别感谢 Viv 分享链接。这对了解发生了什么很有帮助。

克里斯托夫

【讨论】:

  • 那是我的怀疑 :) 不知何故使用错误的调度程序或同步上下文调用 StartNew。
  • @usr 是的,但是如果您在我发布问题后立即回答了这个问题,我想如果没有所有 cmets,我将无法理解 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
  • 2013-04-04
  • 2018-10-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多