【问题标题】:Task return value, without Task<T> (async/await pattern)任务返回值,没有 Task<T>(异步/等待模式)
【发布时间】:2014-05-16 15:19:28
【问题描述】:

我想写以下内容:

public string GetSomeValue()
{
    //directly return the value of the Method 'DoSomeHeavyWork'...
    var t = DoSomeHeavyWork();
    return t.Result;
}

public Task<string> DoSomeHeavyWork()
{
    return Task.Run(() => {
        // do some long working progress and return a string
        return "Hello World!";
    });
}

如您所见,从 DoSomeHeavyWork() 返回结果我使用了 Task.Result 属性,它工作正常,但根据研究,这将阻塞线程。

我想为此使用异步/等待模式,但似乎找不到如何做到这一点。 如果我用我目前的知识对 async/await 做同样的事情,我总是会得到这样的结果:

public async Task<string> GetSomeValue()
{
    //directly return the value of the Method 'DoSomeHeavyWork'...
    var t = DoSomeHeavyWork();
    return await t;
}

public Task<string> DoSomeHeavyWork()
{
    return Task.Run(() => {
        // do some long working progress and return a string
        return "Hello World!";
    });
}

这个解决方案不太符合我的需求,因为我只想返回字符串而不是 Task&lt;string&gt;,如何通过 async/await 来实现?

【问题讨论】:

  • 你为什么不能返回Task&lt;string&gt;,因为当你await它返回一个string。这不是你想要的吗?

标签: c# multithreading asynchronous


【解决方案1】:

你不能。

async 的全部意义在于异步运行代码。因此代码返回一个未来的string 值的promise,在.NET 中表示为Task&lt;string&gt;

这样想:如果您的代码调用public string GetSomeValue(),那么当方法返回时,您已经有一个string。根据定义,这是同步的。

在您的示例中,您有“繁重”的工作,我将其解释为“受 CPU 限制”。在这种情况下,只需同步完成工作:

public string DoSomeHeavyWork()
{
  // do some long working progress and return a string
  return "Hello World!";
}

一般来说,API 不应该“撒谎”;如果它们是同步的,那么它们应该具有同步(非Task-returning)签名。

编辑:根据您的评论,“繁重”的工作是 WCF 调用,它受 I/O 限制,而不是 CPU 限制。

在这种情况下,工作自然是异步的。使用异步 WCF 方法(不是 Task.Run),并允许异步在您的代码库中增长:

public async Task<string> GetSomeValueAsync()
{
  //directly return the value of the Method 'DoSomeHeavyWork'...
  var t = DoSomeHeavyWorkAsync();
  return await t;
}

public async Task<string> DoSomeHeavyWorkAsync()
{
  // Call asynchronous WCF client.
  await ...;
  return "Hello World!";
}

【讨论】:

  • 您将如何使用Task.Result 属性解决我的问题,或者您知道更好的方法吗? (如果你知道更好的替代方案,我会对代码 sn-ps 感到高兴)
  • 在我的真实示例中,我正在向客户端调用 WCF 请求,并希望有一个异步运行的方法,以便在服务器调用该方法时不阻塞客户端(服务器/客户端都是 WPF ) 我应该返回 Task 对象而不是解析的字符串/对象吗?
  • 我已经用我喜欢的解决方案编辑了我的答案:直接完成工作。由于“繁重”的工作是 WCF 请求,因此我再次对其进行了编辑。
  • 所以如果 WCF 客户端实现以下接口就没有问题:[OperationContract()] Task&lt;string&gt; GetAccountValue(string accNr, string propertyName); 而不是简单的字符串/对象?
  • 对;任何Task-returning 都是异步的,如果你异步使用它(通过await),一切正常。
猜你喜欢
  • 2014-10-01
  • 2013-04-26
  • 1970-01-01
  • 1970-01-01
  • 2018-04-21
  • 1970-01-01
相关资源
最近更新 更多