【问题标题】:Make Task.Delay continue on the calling thread使 Task.Delay 在调用线程上继续
【发布时间】:2016-03-04 23:48:19
【问题描述】:

考虑这种方法:

//Called on a known thread
    public async void ThreadSleep()
    {
     while(itemsInQueue)
      {
        //This call is currently on Thread X
        await Task.Delay(5000);
       //This needs to be on the thread that the method was called on
        DoSomeProcessing();
       }
    }

我假设 Task.Delay 在不同的线程上执行异步并在同一个线程上恢复。这对我来说不是很明显。如何让方法在 Thread X 上继续?

PS:ThreadSleep 方法在非 UI 线程上执行

编辑:1) 为简单起见,添加了 W.Brian 的代码示例。

2) 是的,这个例子正是……一个例子。

3) Thread.Delay 的目的只是在处理之间增加一些延迟。

【问题讨论】:

  • 为什么要继续调用线程?
  • @svick:我为什么不想要它?数据同步一个。重入问题。我可以想到很多原因,为什么对方法的调用需要在预先确定的线程上。
  • 您列出的所有内容都已通过正确返回 async Task 而不是 async void 得到修复。 You should never return async void unless you are doing it to be compatible with a event handler。如果我不正确,您能否用一个示例更新您的问题,您需要它位于同一个线程上(并且该线程不是 UI 线程)。
  • 好吧,它并没有修复这个人为的例子,它修复了数据同步和重入问题,尽管这就是你告诉 svick 你为什么需要它的原因。如果您可以发布一个为什么需要它的真实示例,我可以发布一个答案,解释如何做到这一点或解决方法将如何实现相同的目标。我不能用你当前的例子来做,因为我不知道DoSomeProcessing() 后面的“为什么”每次都必须在同一个非 UI 线程上,如果我知道要求的原因,我可以满足要求。
  • @bobbyalex 我对你的问题投了反对票,因为你要求的东西通常是一种不好的做法,而没有给出任何理由说明为什么它对你的情况有意义。这也让你的问题听起来像the XY problem

标签: c# task-parallel-library


【解决方案1】:

您需要创建自己的同步上下文(就像 UI 线程一样)。

There's a pretty good article on MSDN that helps to understand the problem and how to create a solution.

介意我问你为什么必须继续同一个线程吗? 通常它不应该在使用新线程时创建和发出,因为上下文被保留了。

如果您需要在更深层次的调用之间保留某种上下文(就像您对 ThreadLocal 所做的那样),我建议您使用新的 AsyncLocal 来实现这一目标。 它确保不可变对象保持在异步上下文中,即使线程发生更改(请参阅:How do the semantics of AsyncLocal differ from the logical call context?)。

【讨论】:

  • 如果您检查示例,您会发现每次运行 while 循环时,它都会在不同的线程上执行 DoSomeProcessing,这是不可接受的。
  • @bobbyalex:最初是正确的;但是一旦您创建了“SingleThreadSynchronizationContext”并在 Run() 方法中运行您的委托,该线程将专门为您自己的调度程序保留(示例在文章的最底部)。
【解决方案2】:
await Task.Delay(5000).ConfigureAwait(true);

调用ConfigureAwait(true) 应该可以工作,因为它可以确保与原始线程相同的上下文,即使线程发生更改也是如此。这假设 ThreadLocal<T> 没有被使用,在这种情况下 async/await 通常会导致问题,如果您无法更改其余代码,则可能首选 Thread.Sleep

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    • 2015-12-19
    • 2017-08-16
    • 1970-01-01
    相关资源
    最近更新 更多