Does await Task.CompletedTask mean the async method will run synchronously?

27 浏览
0 Comments

Does await Task.CompletedTask mean the async method will run synchronously?

static async Task WaitTaskCompleted()
{
    //在 await Task.CompletedTask 之前会使用线程 A
    await Task.CompletedTask;
    //在 await Task.CompletedTask 之后的代码,是否总是会继续使用线程 A,还是有可能会使用线程 B?
}

\n这意味着 await Task.CompletedTask 总是以同步的方式执行方法?

0
0 Comments

await Task.CompletedTask的出现原因是为了提供一个简单的工厂方法来创建已完成的Task对象。在某些情况下,我们可能需要返回一个已经完成的Task对象,而不需要进行异步操作。例如,在单元测试中模拟一个接口时,我们可能需要返回一个已完成的Task对象作为接口方法的返回值。在这种情况下,我们可以使用Task.FromResult或Task.CompletedTask方法来创建一个已完成的Task对象,并直接返回。

然而,如果我们直接在await语句中使用Task.CompletedTask或Task.FromResult创建的Task对象,编译器会生成一个不必要的异步状态机包装器,这在某些情况下可能是一种过度设计。因此,在实际开发中,我们很少直接await一个由Task.CompletedTask或Task.FromResult创建的Task对象。

解决这个问题的方法是,在需要返回已完成的Task对象的情况下,我们可以直接返回Task.FromResult或Task.CompletedTask方法创建的Task对象,而不需要使用await语句。这样可以避免生成不必要的异步状态机包装器,提高代码的执行效率。

总之,Task.CompletedTask方法的出现是为了提供一个简单的工厂方法来创建已完成的Task对象。在某些情况下,我们可能需要返回一个已完成的Task对象,而不需要进行异步操作。然而,在实际开发中,我们很少直接await一个由Task.CompletedTask或Task.FromResult创建的Task对象,以避免生成不必要的异步状态机包装器。解决这个问题的方法是直接返回Task.FromResult或Task.CompletedTask方法创建的Task对象,而不需要使用await语句。这样可以提高代码的执行效率。

0
0 Comments

await Task.CompletedTask意味着异步方法将以同步方式运行吗?

这个问题的出现原因是await关键字的工作原理。当遇到第一个未完成的awaitable对象时,编译器会自动调用主要的continuation代码。

我们可以在sharplab的链接中看到这一点。具体来说,在下面的代码中:

awaiter = Task.CompletedTask.GetAwaiter();
if (!awaiter.IsCompleted)
{
    num = (<>1__state = 0);
    <>u__1 = awaiter;
    <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
    return;
}

是通过AwaitUnsafeOnCompleted(...) + return来实现异步性的。

解决这个问题的方法是使用真正的异步操作,而不是使用Task.CompletedTask。

我们可以创建一个异步方法来替代Task.CompletedTask,然后在其中添加真正的异步操作。这样,我们就可以确保异步方法以异步方式运行,而不是以同步方式运行。

以下是一个示例代码:

async Task MyAsyncMethod()
{
    await Task.Delay(1000); // 真正的异步操作
}

通过使用真正的异步操作,我们可以确保异步方法在遇到await关键字时以异步方式运行,而不是同步方式运行。这样可以提高应用程序的性能和响应能力。

总结起来,使用Task.CompletedTask可能会导致异步方法以同步方式运行。解决这个问题的方法是使用真正的异步操作来替代Task.CompletedTask,以确保异步方法以异步方式运行。

0