关于使用await关键字执行主线程的说明

时间:2019-06-23 10:52:21

标签: .net multithreading asynchronous async-await

我已经阅读了十几篇有关异步/等待的文章,它们都是很棒的读物。但是在所有这些文章中,都没有解决一些困惑/问题。我也在这个论坛上见过(this awesome post) ,但我没有明确的解释,所以我正在寻求您对此事的深入了解。

示例

在下面的Console App示例中,由于未维护同步上下文,因此返回线程ID,即1和5。

与GUI相似的示例将在同一线程上运行,因为在那里保留了同步上下文。

using System;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncConcept
{
    class Program
    {
        static void Main(string[] args)
        {
            AsyncMethod();
            Console.WriteLine("Main Thread: " + (int)AppDomain.GetCurrentThreadId());
            Console.ReadLine();
        }

        public static async void AsyncMethod()
        {
            await Task.Delay(TimeSpan.FromSeconds(5));
            Console.WriteLine("AsyncMethod Thread: " + (int)AppDomain.GetCurrentThreadId());
            Console.ReadLine();
        }
    }
}

问题

当我们将await关键字与I / O调用或API调用一起使用时,仅在主线程上发生await操作吗?

a)如果是,主线程(在GUI情况下为UI线程)如何与方法的其余部分同时继续?

b)如果为否,则违反了异步并等待的无线程生成理论。

1 个答案:

答案 0 :(得分:1)

  

当我们将await关键字与I / O调用或API调用一起使用时,仅在主线程上发生await操作吗?

await发生在运行该方法的任何线程上。在这种情况下,AsyncMethod在主线程上被调用,await在主线程上发生。如果AsyncMethod被UI线程调用,那么await将会在UI线程上发生。

我认为您正在考虑await以某种方式“运行”异步操作,但这根本不会发生。我所说的the await "happening"await

  1. 检查其等待项是否已完成(在这种情况下,“等待项”是从Task.Delay返回的任务)。如果已经完成,它将继续同步执行该方法。
  2. 如果等待项未完成,await(默认情况下)将捕获当前上下文,然后使用该上下文来安排该方法在等待项完成时继续运行。然后await返回。

请注意,如果等待未完成,则该方法返回。在正常情况下,它将返回一个不完整的任务,该任务在async方法完成时完成;在这种情况下,没有返回类型,因此调用async方法完成时,调用代码不容易知道。

  

a)如果是,主线程(在GUI情况下为UI线程)如何与方法的其余部分同时继续?

由于等待未完成,因此await从方法中返回。该方法的其余部分将在等待完成时运行。