Nea*_*eal 288 c# async-await c#-5.0 .net-4.5
我试图以最简单的形式理解异步等待.我想创建一个非常简单的方法,为了这个例子添加两个数字,被授予,它根本没有处理时间,这只是在这里制定一个例子的问题.
private async Task DoWork1Async()
{
int result = 1 + 2;
}
Run Code Online (Sandbox Code Playgroud)
private async Task DoWork2Async()
{
Task.Run( () =>
{
int result = 1 + 2;
});
}
Run Code Online (Sandbox Code Playgroud)
如果我等待DoWork1Async()
代码将同步或异步运行?
我是否需要包装同步代码Task.Run
以使方法等待和异步,以便不阻止UI线程?
我试图弄清楚我的方法是否是一个Task
或返回Task<T>
我是否需要包装代码Task.Run
以使其异步.
愚蠢的问题我很确定,但是我在网上看到人们正在等待代码中没有任何异步并且未包含在Task.Run
或中的示例StartNew
.
Ste*_*ary 559
首先,让我们清楚一些术语:"asynchronous"(async
)意味着它可以在启动之前将控制权交还给调用线程.在一种async
方法中,那些"屈服"点是await
表达式.
这与术语"异步"非常不同,因为MSDN文档多年来使用(mis)表示"在后台线程上执行".
进一步混淆这个问题,async
与"等待"有很大不同; 有一些async
方法的返回类型是不可等的,许多方法返回不等待的类型async
.
足够他们不是 ; 这是他们的意思:
async
关键字允许异步方法(即,它允许await
表达式).async
方法可以返回Task
,, Task<T>
或(如果必须)void
.Task
和Task<T>
.因此,如果我们将您的问题重新表述为"如何以一种可以等待的方式在后台线程上运行操作",那么答案就是使用Task.Run
:
private Task<int> DoWorkAsync() // No async because the method does not need await
{
return Task.Run(() =>
{
return 1 + 2;
});
}
Run Code Online (Sandbox Code Playgroud)
(但这种模式很差;见下文).
但是如果你的问题是"我如何创建一个async
可以回复其调用者而不是阻塞"的方法,那么答案就是声明方法async
并使用await
它的"让步"点:
private async Task<int> GetWebPageHtmlSizeAsync()
{
var client = new HttpClient();
var html = await client.GetAsync("http://www.example.com/");
return html.Length;
}
Run Code Online (Sandbox Code Playgroud)
因此,事物的基本模式是让async
代码依赖于await
表达式中的"等待" .这些"等待"可以是其他async
方法或只是常规方法返回等待.常规方法返回Task
/ Task<T>
可使用Task.Run
到在后台线程执行代码,或(更常见),他们可以用TaskCompletionSource<T>
或它的快捷方式(之一TaskFactory.FromAsync
,Task.FromResult
等等).我不建议包装整个方法Task.Run
; 同步方法应该具有同步签名,并且它应该留给消费者是否应该包装在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());
...
}
Run Code Online (Sandbox Code Playgroud)
我的博客上有async
/ await
介绍 ; 最后是一些很好的后续资源.MSDN文档async
也非常好.
Ron*_*mos 22
在使用异步装饰方法时要记住的最重要的事情之一 是至少在方法中有一个await运算符.在您的示例中,我将使用TaskCompletionSource将其翻译为如下所示.
private Task<int> DoWorkAsync()
{
//create a task completion source
//the type of the result value must be the same
//as the type in the returning Task
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
Task.Run(() =>
{
int result = 1 + 2;
//set the result to TaskCompletionSource
tcs.SetResult(result);
});
//return the Task
return tcs.Task;
}
private async void DoWork()
{
int result = await DoWorkAsync();
}
Run Code Online (Sandbox Code Playgroud)
zhe*_* yu 12
当您使用Task.Run运行方法时,Task从线程池中获取一个线程来运行该方法.因此,从UI线程的角度来看,它是"异步的",因为它不会阻止UI线程.这对于桌面应用程序来说很好,因为您通常不需要很多线程来处理用户交互.
但是,对于Web应用程序,每个请求都由线程池线程提供服务,因此可以通过保存此类线程来增加活动请求的数量.经常使用线程池线程来模拟异步操作对于Web应用程序是不可扩展的.
True Async不一定涉及使用线程进行I/O操作,例如文件/数据库访问等.您可以阅读此内容以了解I/O操作不需要线程的原因.http://blog.stephencleary.com/2013/11/there-is-no-thread.html
在您的简单示例中,它是纯CPU绑定计算,因此使用Task.Run很好.