我试图以最简单的形式理解异步等待。我想创建一个非常简单的方法,为了这个例子而将两个数字相加,当然,它根本没有处理时间,只是在这里制定一个示例的问题。
private async Task DoWork1Async()
{
int result = 1 + 2;
}
private async Task DoWork2Async()
{
Task.Run( () =>
{
int result = 1 + 2;
});
}
如果我等待,代码是同步运行还是异步运行?DoWork1Async()
我是否需要包装同步代码以使方法可等待和异步,以免阻塞 UI 线程?Task.Run
我试图弄清楚我的方法是否是 or 返回是否需要包装代码以使其异步。Task
Task<T>
Task.Run
我在网上看到一些例子,人们正在等待代码,这些代码内部没有任何异步代码,也没有包装在 or 中。Task.Run
StartNew
首先,让我们澄清一些术语:“异步”()意味着它可以在启动之前将控制权交还给调用线程。在方法中,这些“屈服”点是表达式。async
async
await
这与术语“异步”非常不同,因为 MSDN 文档多年来(错误地)使用术语来表示“在后台线程上执行”。
进一步混淆问题,与“等待”有很大不同;有些方法的返回类型不可等待,而返回的可等待类型则有许多方法不是。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;
});
}
(但这种模式是一种糟糕的方法;见下文)。
但是,如果你的问题是“我如何创建一个可以让回给其调用方而不是阻塞的方法”,答案是声明该方法并用于其“屈服”点:async
async
await
private async Task<int> GetWebPageHtmlSizeAsync()
{
var client = new HttpClient();
var html = await client.GetAsync("http://www.example.com/");
return html.Length;
}
因此,事物的基本模式是让代码在其表达式中依赖于“awaitables”。这些“awaitables”可以是其他方法,也可以只是返回awaitable的常规方法。返回 / 的常规方法可用于在后台线程上执行代码,或者(更常见的)它们可以使用或其快捷方式之一(、等)。我不建议将整个方法包装在 ;同步方法应该有同步签名,是否应该包装在 :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());
...
}
我的博客上有一个/介绍;最后是一些很好的后续资源。MSDN文档也异常出色。async
await
async
使用 async 装饰方法时要记住的最重要的事情之一是,方法中至少有一个 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 Task DoWork()
{
int result = await DoWorkAsync();
}
使用 Task.Run 运行方法时,Task 会从线程池中获取一个线程来运行该方法。因此,从 UI 线程的角度来看,它是“异步”的,因为它不会阻止 UI 线程。这对于桌面应用程序来说很好,因为您通常不需要很多线程来处理用户交互。
但是,对于 Web 应用程序,每个请求都由线程池线程提供服务,因此可以通过保存此类线程来增加活动请求的数量。频繁使用线程池线程来模拟异步操作对于 Web 应用程序是不可扩展的。
真正的异步不一定涉及使用线程进行 I/O 操作,例如文件/数据库访问等。您可以阅读本文以了解为什么 I/O 操作不需要线程。http://blog.stephencleary.com/2013/11/there-is-no-thread.html
在您的简单示例中,它是一个纯粹的 CPU 密集型计算,因此使用 Task.Run 很好。
模板简介:该模板名称为【是否必须将 Task.Run 放入方法中才能使其异步?】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【C#】栏目查找您需要的精美模板。