【问题标题】:How I'll access this Task <String> return value in C#?我将如何在 C# 中访问此任务 <String> 返回值?
【发布时间】:2017-05-23 08:21:57
【问题描述】:

我正在关注@StephenHaunts 的这篇博文https://stephenhaunts.com/2014/10/10/simple-async-await-example-for-asynchronous-programming/#comments

LongRunningOperation 内部代码中最后一个返回语句的目的是什么。

private static async Task<string> LongRunningOperation()
{
     int counter;    
     for (counter = 0; counter < 50000; counter++)
     {
         Console.WriteLine(counter);
     }    
     return "Counter = " + counter;
}

现在我知道的是:

  1. 当我在Task.Run 中调用这个LongrunningOperation 时,它应该返回这个等待的方法默认返回的任何内容。那么为什么它不这样做。

  2. 如果我使用Task.Result 属性,那么它将同步运行并阻塞调用线程,不推荐这样做。

我想问的是:

  1. 如何在调用点打印这个返回值?

  2. 为什么@Stephen 在不需要的时候写了那个声明?

提前致谢。

【问题讨论】:

  • 你说的在不需要的时候写了那个语句是什么意思?该方法的返回类型是async Task&lt;string&gt;,当然你必须返回一个字符串,否则它不会编译。

标签: c# .net multithreading console async-await


【解决方案1】:

代码中最后一个return 语句的用途是什么,在LongRunningOperation 中。

返回字符串“Counter = 50000”并证明循环已经完成。这不是很有用,但显然,这是一个玩具示例。您可以将您的方法声明为 static async Task 而不是 static async Task&lt;string&gt; 并且不返回值。

当我在Task.Run 中调用这个LongrunningOperation 时,它应该返回这个等待的方法默认返回的任何内容。那么为什么不这样做呢。

是什么让您认为它没有这样做?下面的sn-p是不是没有返回预期的结果?

string s = await Task.Run(() => LongrunningOperation());
// s should now contain "Counter = 50000".

注意:在没有await 的情况下调用Task.Run 将返回可能未完成的任务而不是结果。

如果我使用Task.Result 属性,那么它将同步运行并阻塞调用线程,不推荐这样做。

没错,这就是为什么你不应该这样做。

如何在调用点打印这个返回值?

通过对返回值做一些事情。通过将其分配给字符串(如上所示)或直接打印:

Console.WriteLine(await Task.Run(() => LongrunningOperation()));

为什么@Stephen 在不需要的时候写了那个声明?

那个,你得问斯蒂芬。 :-)

【讨论】:

  • 值得注意的是,严格来说,LongrunningOperation 将始终同步运行,因为这是一个 CPU 绑定操作,即使包裹在 Task.Run 中也是如此。唯一的区别是后者在另一个线程中执行(但同样是同步的)。
  • @FedericoDipuma:这取决于您对“(a)同步”的定义。有些人会争辩说,多线程在定义上是“异步的”,但你是对的,它不是通常的C# async-await 意义上的“异步”。
  • @FedericoDipuma,哦,那你能给我一个简单的基于控制台的 async.await 示例,它会以各种方式异步运行。根据我的理解,上面的示例是异步的,因为它不会停止调用线程。
  • @Heinzi,非常感谢帮助我理解这一点。
  • @Eqra 从 C# 的角度来看,async 操作未绑定到 CPU。纯异步操作通常是 I/O 操作(磁盘、网络等),在等待完成时不会阻塞任何线程。 Stephen 在his blog 中以Task.Run 为例更好地解释了这一点。如果您有进一步的疑问,您最好创建另一个问题,这太宽泛,无法在 cmets 中解释。
【解决方案2】:

一个简单的

private async Task DoSomething()
{
  var counter = await LongRunningOperation();
  //More code.
}

会的。

编辑:

你也可以这样做:

private void DoSomething()
{
  var counter = LongRunningOperation().GetAwaiter().GetResult();
  //More code
}

如果你不想让方法异步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-12
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    相关资源
    最近更新 更多