C# 同步实现异步方法

C# 同步实现异步方法,c#,asynchronous,task,C#,Asynchronous,Task,我有一个接口,它迫使我实现(异步)任务: 我想实现这个方法,但我不会等待任何东西。尽管我必须等待一些东西或返回一些任务,否则我的代码无法编译: public class MyImplementation: IAuthenticationTokenProvider { public async Task CreateAsync(AuthenticationTokenCreateContext context) { /// do something synchron

我有一个接口,它迫使我实现(异步)任务:

我想实现这个方法,但我不会等待任何东西。尽管我必须等待一些东西或返回一些任务,否则我的代码无法编译:

public class MyImplementation: IAuthenticationTokenProvider
{
    public async Task CreateAsync(AuthenticationTokenCreateContext context) 
    {
        /// do something synchronously.

        await something here? ??
    }
}

我的问题是:在不异步执行某些操作的情况下,如何实现此方法?我已经找到了两种解决方案(wait
task.Yield()
,或
wait task.Run(()=>{}))
,但我无法完全理解正确的实现方式和原因。

只需在不等待的情况下实现该方法:

public async Task<Foo> GetFooAsync()
{
    return new Foo();
}
公共异步任务GetFooAsync() { 返回新的Foo(); } 你不等待什么都没关系。异步方法不要求等待任何东西(尽管编译器会警告您没有等待任何东西)

如果您不想要aysnc方法的开销(与异步“状态机”相关联的成本可能不受欢迎),那么您可以

public Task<Foo> GetFooAsync()
{
    return Task.FromResult(new Foo());
}
公共任务GetFooAsync() { 返回Task.FromResult(new Foo()); }
我的解决方案是返回一个
任务
,该任务表示已执行的同步方法的结果。这样,您就可以在异常出现时维护异步方法的语义,而不需要异步状态机的开销。有趣的是,我实际上是出于同样的原因在同一个界面上这么做的

我有一个扩展方法:

    public static Task AsCompletedTask<T>(this Action<T> func, T arg)
    {
        var tcs = new TaskCompletionSource<VoidResult>();
        try
        {
            func(arg);
            tcs.SetResult(voidResult);
        }
        catch (Exception e)
        {
            tcs.SetException(e);
        };

        return tcs.Task;
    }
public static Task AsCompletedTask(此操作函数,T参数)
{
var tcs=new TaskCompletionSource();
尝试
{
func(arg);
tcs.SetResult(voidResult);
}
捕获(例外e)
{
tcs.SetException(e);
};
返回tcs.Task;
}
然后我通过以下方式调用:

    public Task CreateAsync(AuthenticationTokenCreateContext context)
    {
        return ((Action<AuthenticationTokenCreateContext>)Create).AsCompletedTask(context);
    }
公共任务CreateAsync(AuthenticationTokenCreateContext上下文) { 返回((操作)创建).AsCompletedTask(上下文); }
顺便说一句,我讨厌这个名字。如果有人有更好的建议,我洗耳恭听。

如果你不等待任何东西,你的代码应该编译得很好——它实际上不会是异步的。如果在您的情况下,基本上有一个不执行任何IO的快速实现,那么这可能没什么问题,但否则您应该真正异步地执行操作……如果我这样做,我在编译时会收到一条警告:“Async方法缺少'await'运算符,并且将同步运行”。为什么我会收到这个警告?这有什么关系呢?警告本身就说明了问题——您有一个异步方法,但它是同步完成的。在你的情况下,这可能是你想要的。如果不知道
CreateAsync
方法的主体是做什么的,很难判断。如果它总是很快,那就没关系了,你可以对这段代码的警告进行抑制。让我们看看我是否做对了。在我的例子中,我希望编写以下代码:public Task CreateAsync(AuthenticationTokenCreateContext){return Task.FromResult(0);},因为它不是异步的?如果您实际上不想做任何异步的事情,您可以这样做。但我们不知道同步运行所有代码是否合适,因为我们不知道这些代码是什么。正如hvd在评论中提到的那样,这在异常处理方面效果不佳——除了可能的参数验证之外,异步方法通常会返回错误的任务,而不是抛出异常。而不是担心成本(因为这可能是一种微观优化),如果
new Foo()
抛出异常,请担心效果上的差异:在
async
版本中,返回一个任务,指示该任务未成功完成。在另一个版本中,根本不会返回任何任务。问题是我不是在处理任务,而是只处理一个任务。所以这是一个异步的空。因此,从中创建结果并不重要。@ClarkKent
Task
实现了
Task
,因此您只需返回
Task.FromResult(0)
,即可满足
Task
的(非泛型)返回类型。任务的“值”不会被使用。
    public Task CreateAsync(AuthenticationTokenCreateContext context)
    {
        return ((Action<AuthenticationTokenCreateContext>)Create).AsCompletedTask(context);
    }