简体   繁体   English

异步的行为等待新线程

[英]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: 所以根据这个,我的问题是:

  1. 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 ,它是否会被释放以用于其他工作?
  2. If the preceding is true, will the thread simply end and a thread pool thread take its place when the SomeOtherAsyncMethod returns? 如果前面的条件为真,那么当SomeOtherAsyncMethod返回时,线程是否会简单地结束并且线程池线程取代它?
  3. How would I go about issuing the StartThread function on a thread pool thread rather than a managed thread? 我如何在线程池线程而不是托管线程上发布StartThread函数?
  4. 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? 当一个等待的方法返回其调用者时,它是否被强制在调用它的线程上恢复,或者任何空闲线程可以取代它?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM