C# 如何将无效的同步方法转换为异步方法?

C# 如何将无效的同步方法转换为异步方法?,c#,async-await,C#,Async Await,所以我有一个方法,它只有同步操作: public void Foo(){ //do something synchronously if(x == 0) return; else if(x < 5): //do something return; // do something extra } 我不确定这一点,因为CompletedTask属性表明它是一个成功的操作,但并非所有这些条件都是如此 编辑:在注释中

所以我有一个方法,它只有同步操作:

public void Foo(){
    //do something synchronously
    if(x == 0)
        return;
    else if(x < 5):
        //do something
        return;
    // do something extra
}
我不确定这一点,因为
CompletedTask
属性表明它是一个成功的操作,但并非所有这些条件都是如此

编辑:在注释中解析。仅仅因为方法用“async”后缀表示,并不意味着它需要
async
修饰符。该函数将按如下所示编写,以遵守接口更改:

public Task FooAsync(){
    //do something synchronously
    if(x == 0)
        return Task.CompletedTask;
    else if(x < 5):
        //do something
        return Task.CompletedTask;
    // do something extra
    return Task.CompletedTask;
}
公共任务fooancy(){ //同步做某事 如果(x==0) 返回Task.CompletedTask; 否则,如果(x<5): //做点什么 返回Task.CompletedTask; //做些额外的事 返回Task.CompletedTask; }
正如其他人所指出的,类似于任务的返回类型是异步签名,而
async
是异步实现细节。完全可能有一个
任务
-返回方法不是
异步

然而,有一个重要的警告:例外。当异步(即,
任务
-like返回)方法失败时,预期的语义是捕获异常并将其放在返回的任务上

因此,您不希望只返回
CompletedTask
;您还需要捕获异常并使用
任务。FromException

public Task FooAsync()
{
  try
  {
    //do something synchronously
    if(x == 0)
        return Task.CompletedTask;
    else if(x < 5):
        //do something
        return Task.CompletedTask;
    // do something extra
    return Task.CompletedTask;
  }
  catch (Exception ex)
  {
    return Task.FromException(ex);
  }
}
这种方法的问题是,除非包含丑陋的pragmas来禁用编译器警告,否则会收到编译器警告。如果您发现自己需要在多个地方执行此操作,我建议使用一些helper方法():

公共静态类TaskHelper
{
#布拉格警告禁用1998
公共静态异步任务ExecutEastTask(操作函数)
#布拉格警告恢复1998
{
func();
}
#布拉格警告禁用1998
公共静态异步任务执行任务(Func Func)
#布拉格警告恢复1998
{
返回func();
}
}
这样使用:

public Task FooAsync() => TaskHelper.ExecuteAsTask(() =>
{
    //do something synchronously
    if(x == 0)
        return;
    else if(x < 5):
        //do something
        return;
    // do something extra
});
public Task fooancy()=>TaskHelper.executeEastTask(()=>
{
//同步做某事
如果(x==0)
返回;
否则,如果(x<5):
//做点什么
返回;
//做些额外的事
});

它允许您快速轻松地包装同步方法。

仅仅因为接口要求它返回任务,并不意味着它必须标记为异步。您可以不将其标记为async,让返回类型为Task,然后
返回Task.CompletedTask
。只需
返回Task.CompletedTask
,就可以了。忘记
async
await
No….仅仅因为接口用-async后缀声明方法名称并不意味着它必须标记为async。不需要时将其标记为异步只会引入不必要的状态机。@avhh该接口只会指示它返回一个
任务
。只有当您必须使用
await
时,才需要使用
async
关键字;如果您的某些代码应该在异步调用后运行,则只需要使用
await
关键字,这与您的代码不同。您可能会发现这很有趣:。省略async/await将在出现异常时更改方法的行为。再次抱歉;),正在用
任务包装异常。FromException
建议仅满足抛出异常的异步等待“契约”?@Basin:这更像是一个返回契约的任务,而不是一个
async
/
等待
契约。是的,它提供了预期的语义。
#pragma warning disable 1998
public async Task FooAsync()
#pragma warning restore 1998
{
    //do something synchronously
    if(x == 0)
        return;
    else if(x < 5):
        //do something
        return;
    // do something extra
}
public static class TaskHelper
{
#pragma warning disable 1998
    public static async Task ExecuteAsTask(Action func)
#pragma warning restore 1998
    {
        func();
    }

#pragma warning disable 1998
    public static async Task<T> ExecuteAsTask<T>(Func<T> func)
#pragma warning restore 1998
    {
        return func();
    }
}
public Task FooAsync() => TaskHelper.ExecuteAsTask(() =>
{
    //do something synchronously
    if(x == 0)
        return;
    else if(x < 5):
        //do something
        return;
    // do something extra
});