没有等待或返回的C#异步任务方法

pix*_*xel 10 c# task async-await

我有一个接口我在两个地方实现,如:

interface I 
{ 
   Task DoSomething();
}
Run Code Online (Sandbox Code Playgroud)

该接口具有异步Task DoSomething方法API,然后在A类中实现,如:

class A : I {....}

class B : I {....}
Run Code Online (Sandbox Code Playgroud)

在A类中,DoSomething的实现如下所示,这是正常的:

public async Task DoSomething()
{
    if (...)
    {
        await DoIt();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,在B类中,DoSomething()的实现不应该做任何事情.所以,它的实现看起来像这样:

public async Task DoSomething()
{
    // nothing
}
Run Code Online (Sandbox Code Playgroud)

这编译但我不确定除了方法没用之外,做这样的事情是多么正确.

但在这种情况下"无用"在这种情况下是可以的,因为它的实现只是因为实现接口I的B类需要它.

我想知道这是否是一种正确的方法来实现一个返回异步任务但没有等待或返回的方法?我知道这个方法很简单,无法同步执行,因为没有调用await.

更新:此处已经提出了类似的问题,我在询问这一问题之前已经检查了所有这些问题.没有人问我要问的是什么

sel*_*ape 29

public Task DoSomething()
{
    return Task.CompletedTask;
}
Run Code Online (Sandbox Code Playgroud)

不需要async.

如果您使用的是旧版本的.NET,请使用以下命令:

public Task DoSomething()
{
    return Task.FromResult(0);
}
Run Code Online (Sandbox Code Playgroud)

如果您发现需要返回结果但仍然不需要await任何东西,请尝试;

public Task<Result> DoSomething()
{
    return Task.FromResult(new Result())
}
Run Code Online (Sandbox Code Playgroud)

或者,如果你真的想使用异步(不推荐);

public async Task<Result> DoSomething()
{
    return new Result();
}
Run Code Online (Sandbox Code Playgroud)

  • 我知道不建议使用第四个选项,但您没有给出原因? (3认同)
  • @ m3z - 编译器会生成一条警告:"异步方法缺少等待运算符并将同步运行".但更重要的是,编译器将为一个非常简单的方法生成一个完整的`IAsyncStateMachine`.一个智能编译器可能会对此进行优化,但是从对https://sharplab.io/的简短访问来看,似乎它有可能不会出现,并且在NET47x上,对于异步方法而言,JIT为259字节的x86程序集.用于同步. (2认同)

Jan*_*kke 7

我看到大多数人更喜欢省略async和使用Task.ComletedTask。但是即使await不使用,在异常处理上还是有很大区别的

考虑下面的例子

static async Task Main(string[] args)
{

    Task task = test(); // Will throw exception here
    await task;

    Task taskAsync = testWithAsync();
    await taskAsync; // Will throw exception here
}

static Task test()
{
    throw new Exception();
    return Task.CompletedTask; //Unreachable, but left in for the example
}

static async Task testWithAsync()
{
    throw new Exception();
}
Run Code Online (Sandbox Code Playgroud)

使用

test().ContinueWith(...); 或者 Task.WhenAll(test())

可能会导致意外行为。

因此,我更喜欢async而不是Task.CompletedTaskor Task.FromResult