任务返回值,没有Task <T>(异步/等待模式)

Ran*_*dom 6 c# multithreading asynchronous

我想写下面的内容:

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!";
    });
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,DoSomeHeavyWork()我已经使用了Task.Result属性返回结果,这可以正常工作,但根据研究,这将阻止线程.

我想使用async/await模式,但似乎无法找到如何做到这一点.如果我用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!";
    });
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案不太适合我的需求,因为我想只返回字符串而不是a Task<string>,如何用async/await实现呢?

Ste*_*ary 11

你不能.

整个过程async就是异步运行代码.所以代码返回一个未来值的承诺string,用.NET表示Task<string>.

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

在你的例子中,你有"沉重"的工作,我解释为"CPU限制".在这种情况下,只需同步完成工作:

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

一般来说,API不应该"撒谎"; 如果它们是同步的,那么它们应该具有同步(非Task退回)签名.

编辑:根据您的评论,"重"工作是一个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!";
}
Run Code Online (Sandbox Code Playgroud)