[英]Behavior of async await with new threads
I am trying to understand the precise behavior of async/await and am having a small amount of trouble wrapping my head around it. 我试图了解async / await的精确行为,并且在我周围缠绕时遇到了一些麻烦。
Consider this example: 考虑这个例子:
public async void StartThread()
{
while(true){
SomeOtherClass.SomeSynchronousStuff();
var something = await SomeOtherClass.SomeOtherAsyncMethod();
}
}
public void ConstructorForThisClass()
{
Thread thread = new Thread(StartThread);
thread.Start();
}
My understanding of async/await is that what is happening under the covers is that the compiler is essentially turning your code into a bunch of callbacks and storing state objects for each one. 我对async / await的理解是,幕后发生的事情是编译器本质上是将代码转换成一堆回调并为每个回调存储状态对象。
So according to this, my questions are: 所以根据这个,我的问题是:
SomeOtherAsyncMethod
, will it be freed up to work on other work? 意思是,当线程正在等待SomeOtherAsyncMethod
,它是否会被释放以用于其他工作? SomeOtherAsyncMethod
returns? 如果前面的条件为真,那么当SomeOtherAsyncMethod
返回时,线程是否会简单地结束并且线程池线程取代它? StartThread
function on a thread pool thread rather than a managed thread? 我如何在线程池线程而不是托管线程上发布StartThread
函数? Will the newly created thread be running asynchronously? 新创建的线程是否会异步运行?
Your wording is a bit problematic. 你的措辞有点问题。 The creation of the thread is completely synchronous. 线程的创建是完全同步的。
Meaning, while the thread is awaiting the SomeOtherAsyncMethod, will it be freed up to work on other work? 意思是,当线程正在等待SomeOtherAsyncMethod时,它是否会被释放以用于其他工作?
You're manually creating a thread using the Thread
class, not a Threadpool Thread. 您是使用Thread
类手动创建线程,而不是Threadpool线程。 It isn't shared inside the AppDomain. 它不在AppDomain中共享。 It will be freed up once it hits the first await
keyword, but since you use it in an endless while
loop, it won't get used for any other work other than that. 它会被释放,一旦它击中第一await
关键字,但因为你在一个无限使用它while
循环,它不会用于比其他任何其他工作。
If the preceding is true, will the thread simply end and a thread pool thread take its place when the SomeOtherAsyncMethod returns? 如果前面的条件为真,那么当SomeOtherAsyncMethod返回时,线程是否会简单地结束并且线程池线程取代它?
Disregarding the former, since you don't use ConfigureAwait(false)
, then the continuation will run on an arbitrary ThreadPool thread. 忽略前者,因为你不使用ConfigureAwait(false)
,所以继续将在任意ThreadPool线程上运行。 But that really depends on the context. 但这实际上取决于背景。 Since you're running this delegate on a new Thread, that's what happens. 由于您在新线程上运行此委托,所以会发生这种情况。 But if you were, say, run this from the UI thread, then the continuation would of attempted to marshal itself to the UI message loop via the relevant TaskScheduler
and the corresponding SynchronizationContext
. 但是,如果你是从UI线程运行它,那么继续尝试通过相关的TaskScheduler
和相应的SynchronizationContext
将自身编组到UI消息循环中。
How would I go about issuing the StartThread function on a thread pool thread rather than a managed thread? 我如何在线程池线程而不是托管线程上发布StartThread函数?
All threads initiated by the Thread
class and the ThreadPool
class are managed threads. Thread
类和ThreadPool
类启动的所有线程都是托管线程。 If you meant "How do i run this delegate on the threadpool", than the answer is via Task.Run
or via the ThreadPool
static class. 如果你的意思是“如何在ThreadPool
Task.Run
运行此委托”,那么答案是通过Task.Run
或通过ThreadPool
静态类。
When an awaitable method returns to its caller, is it forced to resume on the thread that calls it or can any free thread take its place? 当一个等待的方法返回其调用者时,它是否被强制在调用它的线程上恢复,或者任何空闲线程可以取代它?
If ran without ConfigureAwait(false)
, it is forced onto the current TaskScheduler
and its underlying SynchronizationContext
. 如果在没有ConfigureAwait(false)
情况下运行,它将被强制转换为当前的TaskScheduler
及其底层的SynchronizationContext
。 This means that if you run inside a UI message loop, and call await
there, it will attempt to post the continuation to it. 这意味着如果你在UI消息循环中运行,并await
那里调用await
,它将尝试将延续发布到它。 If no custom TaskScheduler
is available, it will use the default one, which is the threadpools scheduler. 如果没有可用的自定义TaskScheduler
,它将使用默认的一个,即线程池调度程序。
Bare threads don't work great with async
/ await
. 裸线程与async
/ await
不兼容。
Will the newly created thread be running asynchronously? 新创建的线程是否会异步运行? Meaning, while the thread is awaiting the SomeOtherAsyncMethod, will it be freed up to work on other work? 意思是,当线程正在等待SomeOtherAsyncMethod时,它是否会被释放以用于其他工作?
Actually, the thread will just exit. 实际上,线程将退出。 When StartThread
resumes after the await
, it will execute on a thread pool thread. 当StartThread
后恢复await
,它会执行一个线程池线程。
How would I go about issuing the StartThread function on a thread pool thread rather than a managed thread? 我如何在线程池线程而不是托管线程上发布StartThread函数?
First, you'd want to change the return type of StartThread
from void
to Task
. 首先,您需要将StartThread
的返回类型从void
更改为Task
。 async void
methods are intended for event handlers; async void
方法适用于事件处理程序; using them in other places can cause all sorts of problems. 在其他地方使用它们会导致各种各样的问题。
Then you can just call it via Task.Run
: 然后你可以通过Task.Run
调用它:
var backgroundTask = Task.Run(() => StartThread());
When an awaitable method returns to its caller, is it forced to resume on the thread that calls it or can any free thread take its place? 当一个等待的方法返回其调用者时,它是否被强制在调用它的线程上恢复,或者任何空闲线程可以取代它?
By default, the await
operator will capture the "current context" and resume on that context . 默认情况下, await
运算符将捕获“当前上下文”并在该上下文中继续。 This "current context" is SynchronizationContext.Current
, unless it is null
, in which case it is TaskScheduler.Current
. 这个“当前上下文”是SynchronizationContext.Current
,除非它是null
,在这种情况下它是TaskScheduler.Current
。 Usually, this is either a UI/ASP.NET SynchronizationContext
, or else it's the thread pool context ( TaskScheduler.Default
). 通常,这是UI / ASP.NET SynchronizationContext
,否则它是线程池上下文( TaskScheduler.Default
)。
You may find my async
intro helpful. 您可能会发现我的async
介绍很有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.