首页 > C# > 是否必须将 Task.Run 放入方法中才能使其异步?

是否必须将 Task.Run 放入方法中才能使其异步?

上一篇 下一篇

我试图以最简单的形式理解异步等待。我想创建一个非常简单的方法,为了这个例子而将两个数字相加,当然,它根本没有处理时间,只是在这里制定一个示例的问题。

例 1

private async Task DoWork1Async()
{
    int result = 1 + 2;
}

例 2

private async Task DoWork2Async()
{
    Task.Run( () =>
    {
        int result = 1 + 2;
    });
}

如果我等待,代码是同步运行还是异步运行?DoWork1Async()

我是否需要包装同步代码以使方法可等待和异步,以免阻塞 UI 线程?Task.Run

我试图弄清楚我的方法是否是 or 返回是否需要包装代码以使其异步。TaskTask<T>Task.Run

我在网上看到一些例子,人们正在等待代码,这些代码内部没有任何异步代码,也没有包装在 or 中。Task.RunStartNew

分割线

网友回答:

首先,让我们澄清一些术语:“异步”()意味着它可以在启动之前将控制权交还给调用线程。在方法中,这些“屈服”点是表达式。asyncasyncawait

这与术语“异步”非常不同,因为 MSDN 文档多年来(错误地)使用术语来表示“在后台线程上执行”。

进一步混淆问题,与“等待”有很大不同;有些方法的返回类型不可等待,而返回的可等待类型则有许多方法不是。asyncasyncasync

关于他们不是什么就足够了;以下是它们

  • 关键字允许异步方法(即,它允许表达式)。 方法可以返回 、 或(如果必须)。asyncawaitasyncTaskTask<T>void
  • 遵循特定模式的任何类型都可以等待。最常见的等待类型是 和 。TaskTask<T>

因此,如果我们将您的问题重新表述为“如何以可等待的方式在后台线程上运行操作”,答案是使用 :Task.Run

private Task<int> DoWorkAsync() // No async because the method does not need await
{
  return Task.Run(() =>
  {
    return 1 + 2;
  });
}

(但这种模式是一种糟糕的方法;见下文)。

但是,如果你的问题是“我如何创建一个可以让回给其调用方而不是阻塞的方法”,答案是声明该方法并用于其“屈服”点:asyncasyncawait

private async Task<int> GetWebPageHtmlSizeAsync()
{
  var client = new HttpClient();
  var html = await client.GetAsync("http://www.example.com/");
  return html.Length;
}

因此,事物的基本模式是让代码在其表达式中依赖于“awaitables”。这些“awaitables”可以是其他方法,也可以只是返回awaitable的常规方法。返回 / 常规方法可用于在后台线程上执行代码,或者(更常见的)它们可以使用或其快捷方式之一(、等)。我不建议将整个方法包装在 ;同步方法应该有同步签名,是否应该包装在 :asyncawaitasyncTaskTask<T>Task.RunTaskCompletionSource<T>TaskFactory.FromAsyncTask.FromResultTask.RunTask.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文档也异常出色。asyncawaitasync

分割线

网友回答:

使用 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#】栏目查找您需要的精美模板。

相关搜索
  • 下载密码 lanrenmb
  • 下载次数 204次
  • 使用软件 Sublime/Dreamweaver/HBuilder
  • 文件格式 编程语言
  • 文件大小 暂无信息
  • 上传时间 04-07
  • 作者 网友投稿
  • 肖像权 人物画像及字体仅供参考
栏目分类 更多 >
热门推荐 更多 >
响应式 单页式简历模板 自适应 微信图片 微信文章 企业网站 微信模板 html5 微信公众平台 微信素材
您可能会喜欢的其他模板