我试图以最简单的形式理解异步等待。为了这个例子,我想创建一个非常简单的方法,将两个数字相加,当然,这根本不需要处理时间,只是在这里制定一个例子。
private async Task DoWork1Async() { int result = 1 + 2; }
private async Task DoWork2Async() { Task.Run( () => { int result = 1 + 2; }); }
如果我等待DoWork1Async(),代码是同步运行还是异步运行?
DoWork1Async()
我是否需要包装同步代码Task.Run以使方法可等待和异步,以免阻塞 UI 线程?
Task.Run
我试图弄清楚我的方法是 aTask还是返回Task<T>我是否需要包装代码Task.Run以使其异步。
Task
Task<T>
愚蠢的问题我敢肯定,但我在网上看到一些例子,人们正在等待其中没有任何 async 并且没有包裹在Task.Runor中的代码StartNew。
StartNew
首先,让我们澄清一些术语:“异步”( async) 意味着它可能会在调用线程开始之前将控制权交还给调用线程。在一种async方法中,那些“屈服”点是await表达式。
async
await
这与术语“异步”非常不同,因为 MSDN 文档多年来(误用)来表示“在后台线程上执行”。
进一步混淆问题,async与“等待”有很大不同;有些async方法的返回类型不是可等待的,而许多方法返回的可等待类型不是async.
关于他们 不是 什么已经足够了;它们 是这样的 :
void
因此,如果我们将您的问题重新表述为“如何以等待的方式在 后台线程上Task.Run运行操作”,答案是使用:
private Task<int> DoWorkAsync() // No async because the method does not need await { return Task.Run(() => { return 1 + 2; }); }
(但这种模式是一种糟糕的方法;见下文)。
但是,如果您的问题是“我如何创建一个async可以返回给调用者而不是阻塞的方法”,答案是声明该方法async并await用于其“让步”点:
private async Task<int> GetWebPageHtmlSizeAsync() { var client = new HttpClient(); var html = await client.GetAsync("http://www.example.com/"); return html.Length; }
因此,事物的基本模式是让代码在其表达式async中依赖于“等待对象” 。await这些“等待”可以是其他async方法,也可以只是返回等待的常规方法。Task返回/的常规方法Task<T> 可 用于Task.Run在后台线程上执行代码,或者(更常见)它们可以使用TaskCompletionSource<T>或其快捷方式之一(TaskFactory.FromAsync,Task.FromResult等)。我 不 建议将整个方法包装在Task.Run; 同步方法应该具有同步签名,并且应该由消费者决定是否应该将其包装在 a 中Task.Run:
TaskCompletionSource<T>
TaskFactory.FromAsync
Task.FromResult
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/await介绍;最后是一些很好的后续资源。MSDN 文档async也非常好。