当前位置: 首页 > 知识库问答 >
问题:

必须将Task.Run放入一个方法中使其异步吗?

孙震博
2023-03-14

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

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

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

共有1个答案

柴嘉年
2023-03-14

首先,让我们清理一些术语:“Asynchronous”(Async)意味着它可能会在启动之前将控制权让给调用线程。在async方法中,那些“yield”点是await表达式。

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

为了进一步混淆这个问题,async与“awaitable”有很大区别;有些async方法的返回类型不是可等待的,而许多返回可等待类型的方法不是async

    null

因此,如果我们将您的问题重新表述为“如何才能在后台线程上以可等待的方式运行操作”,那么答案是使用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表达式中的“awaitables”。这些“Awaitables”可以是其他async方法,也可以只是返回Awaitables的常规方法。返回task/task 的常规方法可以使用task.run在后台线程上执行代码,或者(更常见的)可以使用taskcompletionsource 或其快捷方式之一(taskfactory.fromasynctask.fromresult等)。我不建议在task.run中包装整个方法;同步方法应该具有同步签名,并且应该由使用者决定是否将其包装在任务中。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/Await介绍;最后是一些很好的后续资源。async的MSDN文档也非常好。

 类似资料:
  • 注意:还有一个类似的问题,如何在task.run中调用异步方法?但是对于C#来说,选择的答案有反对票,并且没有地址configureaWait。

  • 我给出作为输入文件,一些方法将使用它,但是现在我的reader方法无法检测该文件。 我要将文件放置在哪个目录中....我是否必须在中制定任何maven规范,以检测文件是否存在,并且他们必须读取该文件。

  • 我有一个简短的Node.js脚本,我需要另一个包并从中调用一个异步函数,然后想要打印返回值。如果我只是来自顶层的返回值,那么我会收到一个错误,说我只能在异步函数本身中使用。所以很明显的方法是这样的: 或者: 或者: (聊天 https://chat.stackoverflow.com/transcript/message/54186176#54186176 中归功于VLAZ) 这有效 - 但我想更

  • 问题内容: 我使用的是Spring 4,我注意到了一个奇怪的行为……如果我从普通实例方法多次调用异步方法,那么它们都将在不同的线程中调用,并在随机时间完成。但是,如果我多次从另一个异步方法中调用一个异步方法,那么它们将按顺序完成。我有这样的事情: 我正在使用默认的异步执行器。我应该换一个吗?但是,该执行程序不会重用任何线程,而是每次都启动另一个线程,因此应该没问题……这仅仅是巧合吗?但是我尝试了十

  • 场景1。 同步方法是私有的,位于实现 Runnable 的类中 Main.java MyRunnable.java 场景2。 同步方法是公共和静态的,位于 Main 类中 Main.java MyRunnable.java 问题:以上哪种情况是正确的? 我遵循第二种情况。所以我在主类中有一个同步的方法。这很好。当我将这个同步方法移动到MyRunnable类时,我没有看到任何不同。这很奇怪。我预料它