问题描述
我试图以最简单的形式理解异步等待.为了这个例子,我想创建一个非常简单的方法,将两个数字相加,当然,根本没有处理时间,这只是在这里制定一个例子的问题.
I'm trying to understand async await in the simplest form. I want to create a very simple method that adds two numbers for the sake of this example, granted, it's no processing time at all, it's just a matter of formulating an example here.
private async Task DoWork1Async()
{
int result = 1 + 2;
}
示例 2
private async Task DoWork2Async()
{
Task.Run( () =>
{
int result = 1 + 2;
});
}
如果我等待 DoWork1Async()
代码是同步运行还是异步运行?
If I await DoWork1Async()
will the code run synchronously or asynchronously?
我是否需要用 Task.Run
包装同步代码以使方法可等待和异步,以免阻塞 UI 线程?
Do I need to wrap the sync code with Task.Run
to make the method awaitable AND asynchronous so as not to block the UI thread?
我想弄清楚我的方法是 Task
还是返回 Task
我是否需要用 Task.Run 包装代码
使其异步.
I'm trying to figure out if my method is a Task
or returns Task<T>
do I need to wrap the code with Task.Run
to make it asynchronous.
愚蠢的问题我敢肯定,但我在网上看到一些例子,人们正在等待代码中没有任何异步内容并且没有包含在 Task.Run
或 StartNew
中.
Stupid question I'm sure but I see examples on the net where people are awaiting code that has nothing async within and not wrapped in a Task.Run
or StartNew
.
推荐答案
首先,让我们澄清一些术语:异步"(async
)意味着它可能会在之前将控制权交还给调用线程开始.在 async
方法中,那些yield"点是 await
表达式.
First, let's clear up some terminology: "asynchronous" (async
) means that it may yield control back to the calling thread before it starts. In an async
method, those "yield" points are await
expressions.
这与术语异步"非常不同,因为 MSDN 文档多年来(错误地)使用它来表示在后台线程上执行".
This is very different than the term "asynchronous", as (mis)used by the MSDN documentation for years to mean "executes on a background thread".
为了进一步混淆这个问题,async
与awaitable"非常不同;有一些 async
方法的返回类型是不可等待的,而许多方法返回的可等待类型不是 async
.
To futher confuse the issue, async
is very different than "awaitable"; there are some async
methods whose return types are not awaitable, and many methods returning awaitable types that are not async
.
足够了解他们不是什么;这是它们是:
Enough about what they aren't; here's what they are:
async
关键字允许异步方法(即,它允许await
表达式).async
方法可能返回Task
、Task
或(如果必须)void
.- 任何遵循特定模式的类型都可以等待.最常见的等待类型是
Task
和Task
.
- The
async
keyword allows an asynchronous method (that is, it allowsawait
expressions).async
methods may returnTask
,Task<T>
, or (if you must)void
. - Any type that follows a certain pattern can be awaitable. The most common awaitable types are
Task
andTask<T>
.
因此,如果我们将您的问题重新表述为如何以可等待的方式在后台线程上运行操作",那么答案是使用 Task.Run代码>:
So, if we reformulate your question to "how can I run an operation on a background thread in a way that it's awaitable", the answer is to use Task.Run
:
private Task<int> DoWorkAsync() // No async because the method does not need await
{
return Task.Run(() =>
{
return 1 + 2;
});
}
(但这种模式是一种糟糕的方法;见下文).
(But this pattern is a poor approach; see below).
但如果您的问题是我如何创建一个 async
方法,它可以返回给它的调用者而不是阻塞",答案是声明方法 async
并使用 await
作为它的屈服"点:
But if your question is "how do I create an async
method that can yield back to its caller instead of blocking", the answer is to declare the method async
and use await
for its "yielding" points:
private async Task<int> GetWebPageHtmlSizeAsync()
{
var client = new HttpClient();
var html = await client.GetAsync("http://www.example.com/");
return html.Length;
}
因此,事物的基本模式是让 async
代码依赖于其 await
表达式中的awaitables".这些awaitables"可以是其他async
方法或只是返回awaitables 的常规方法.常规方法返回 Task
/Task
可以 使用 Task.Run
在后台线程上执行代码,或者(更常见)他们可以使用 TaskCompletionSource
或其快捷方式之一(TaskFactory.FromAsync
、Task.FromResult
等).我不建议在 Task.Run
中包装整个方法;同步方法应该有同步签名,是否应该包装在 Task.Run
中应该由消费者决定:
So, the basic pattern of things is to have async
code depend on "awaitables" in its await
expressions. These "awaitables" can be other async
methods or just regular methods returning awaitables. Regular methods returning Task
/Task<T>
can use Task.Run
to execute code on a background thread, or (more commonly) they can use TaskCompletionSource<T>
or one of its shortcuts (TaskFactory.FromAsync
, Task.FromResult
, etc). I don't recommend wrapping an entire method in Task.Run
; synchronous methods should have synchronous signatures, and it should be left up to the consumer whether it should be wrapped in a Task.Run
:
private int DoWork()
{
return 1 + 2;
}
private void MoreSynchronousProcessing()
{
// Execute it directly (synchronously), since we are also a synchronous method.
var result = DoWork();
...
}
private async Task DoVariousThingsFromTheUIThreadAsync()
{
// I have a bunch of async work to do, and I am executed on the UI thread.
var result = await Task.Run(() => DoWork());
...
}
我有一个 async
/等待
介绍在我的博客上;最后是一些很好的后续资源.async
的 MSDN 文档也异常出色.
I have an async
/await
intro on my blog; at the end are some good followup resources. The MSDN docs for async
are unusually good, too.
这篇关于您是否必须将 Task.Run 放在一个方法中以使其异步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!