56

我正在开发一个系统,在该系统中,期望多个客户端对象通过接口实现特定功能,并且我希望该功能与延续异步运行(我希望实现是 I/O 绑定的并且想要确保所有客户端对象尽快完成此功能)。我正在使用 Visual Studio Async CTP Refresh for SP1,使用 C#“5.0”。

在我的抽象类的子对象中强制执行异步行为的推荐做法是什么(见下文)?我不能(显然)使用虚拟方法方法强制使用“异步”方法。我只能要求一个“任务”返回类型。这是否意味着我不应该尝试在子对象中要求异步行为?在那种情况下,返回类型是否应该只是“void”?

公共接口是目前系统设计的一个不幸结果,但这是一个单独的问题。显然,我不能限制任何绕过“BaseFoo”并只实现“IFoo”接口的异步。

这是代码:

public interface IFoo
{
    void Bar(); //NOTE: Cannot use 'async' on methods without bodies.
}

public abstract class BaseFoo : IFoo
{
    public async void Bar()
    {
        await OnBar(); //QUESTION: What is the right "async delegation" pattern?
    }

    protected virtual async Task OnBar()
    {
        await TaskEx.Yield();
    }
}

public class RealFoo : BaseFoo //NOTE: May be implemented by 3rd party
{
    protected override async Task OnBar()
    {
        //CLIENT: Do work, potentially awaiting async calls

        await TaskEx.Yield(); //SECONDARY QUESTION: Is there a way to avoid this if there are no 'awaits' in the client's work?
    }
}
4

2 回答 2

96

是否使用async/await是否实现方法是实现细节。该方法的行为方式是合同细节,应该以正常方式指定。

请注意,如果您使方法返回 aTask或 a ,则更明显的是它是异步的,并且如果不Task<T>异步可能很难实现。

另一方面,如果有一个await表达式永远不会不完整的实现(例如,出于测试目的),你为什么要强迫某人编写一个没有await调用的异步方法呢?您期望实现受 IO 限制,但可能会有特殊情况下实现想要使用硬编码数据等。

基本上你必须在方法的文档中处理这个 - 如果你不能相信实现者会阅读它,你无论如何都没有机会:(

于 2011-06-08T05:34:05.047 回答
21

除了 Jon 的回答之外,如果您遵循基于任务的异步模式,那么您的方法名称应该以 为后缀Async,这表明它是一个异步方法。

如果你正在实现一个接口

public interface IFoo
{
    Task BarAsync();
}

很明显,这应该用async关键字来实现。

于 2014-10-23T11:29:15.973 回答