2015-12-14 34 views
-1

在考虑这个方法:使Task.Delay继续调用线程

//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正在执行不同的线程异步并恢复该同一线程。这对我来说不是很明显。如何让方法继续使用线程X?

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

编辑:1)增加W.Brian的为了简化代码示例。

2)是的,这个例子就是......一个例子。

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

+3

为什么你想继续在调用线程? – svick

+0

不知道这是否只是一个人为的例子,但你应该只调用Task.Run来处理CPU繁重的操作。在这种情况下,你有一个纯粹的异步方法('Task.Delay()'),所以你应该等待它。使用方法签名'async void'而不是'async Task'也是不好的做法,除非你必须因为它是一个偶数句柄。 – kai

+0

@svick:为什么我不想要它?数据同步为一个。重入问题。我可以想到为什么对一个方法的调用需要在预先确定的线程上的很多原因。 – bobbyalex

回答

4

您需要创建自己的同步上下文(如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?)。

+0

如果您查看示例,您将看到每次运行while循环时,它都会在不可接受的其他线程上执行DoSomeProcessing。 – bobbyalex

+0

@bobbyalex:最初这是正确的;但是一旦你创建了“SingleThreadSynchronizationContext”并且在Run()方法中运行你的委托,那么这个线程将专门用于你自己的调度器(例如文章最底部的例子)。 –

0
await Task.Delay(5000).ConfigureAwait(true); 

调用ConfigureAwait(true)应该工作,因为它确保了相同的上下文中原来的线程即使线程的变化。这假定ThreadLocal<T>未被使用,在这种情况下,异步/等待通常会导致问题,如果您不能更改其余代码,则可能首选Thread.Sleep