c# – 到Task.Run或不到Task.Run

假设我有一个包含异步方法的接口,我有两个不同的接口实现.两种实现中的一种是自然异步,而另一种则不是.实现非异步方法的“最正确”方法是什么?
public interface ISomething {
    Task<Foo> DoSomethingAsync();
}

// Normal async implementation
public class Implementation1 : ISomething {
    async Task<Foo> ISomething.DoSomethingAsync() {
        return await DoSomethingElseAsync();
    }
}

// Non-async implementation
public class Implementation2 : ISomething {
    // Should it be:
    async Task<Foo> ISomething.DoSomethingAsync() {
        return await Task.Run(() => DoSomethingElse());
    }
    // Or:
    async Task<Foo> ISomething.DoSomethingAsync() {
        return DoSomethingElse();
    }
}

我试着跟上Stephen Cleary的blog,我知道其中任何一个都没有提供任何异步的好处,而且我对此很满意.第二个对我来说似乎更正确,因为它不会假装不是它的东西,但它确实给出了编译器警告,并且那些加起来并且分散注意力.

如果这会产生影响,那么这些都将在ASP.NET(Web MVC和WebAPI)中.

解决方法

您可以完全放弃async修饰符并使用Task.FromResult同步返回已完成的任务:
Task<Foo> ISomething.DoSomethingAsync()
{
    return Task.FromResult(DoSomethingElse());
}

这会处理警告并具有更好的性能,因为它不需要异步方法的状态机开销.

但是,这有点change the semantics of exception handling.如果这是一个问题,那么您应该使用同步异步方法方法并接受警告(或通过注释将其关闭):

#pragma warning disable 1998
    async Task<Foo> ISomething.DoSomethingAsync() 
#pragma warning restore 1998
    {
        return DoSomethingElse();
    }

正如Stephen Cleary建议您也可以通过等待已完成的任务来处理该警告(同时保持方法同步):

async Task<Foo> ISomething.DoSomethingAsync() 
{
    await Task.FromResult(false); // or Task.CompletedTask in .Net 4.6
    return DoSomethingElse();
}

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...