Как заставить асинхронные дочерние переопределения в C# 5.0

Я работаю над системой, в которой несколько клиентских объектов должны реализовать определенную функцию через интерфейс, и я хочу, чтобы эта функция выполнялась асинхронно с продолжениями (я ожидаю, что реализации будут связаны с вводом-выводом и хотят гарантировать, что все клиентские объекты завершат эту функцию как можно скорее). Я использую обновление Visual Studio Async CTP для SP1 с C# "5.0".

какова рекомендуемая практика применения асинхронных поведение в дочерних объектах моего абстрактного класса (см. ниже)? Я не могу (по-видимому) принудительно использовать методы "async", используя подход виртуального метода. Мне может потребоваться только тип возврата "Task". Означает ли это, что я вообще не должен пытаться требовать асинхронного поведения в дочерних объектах? В этом случае должен ли возвращаемый тип быть просто "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?
    }
}

2 ответов


реализован ли метод с помощью async/await или нет реализация деталь. Как метод должен вести - это деталь контракта, которая должна быть указана обычным способом.

обратите внимание, что если вы сделаете метод return a Task или Task<T>, более очевидно, что он должен быть асинхронным и, вероятно, будет трудно реализовать без быть асинхронным.

С другой стороны, если есть реализация (например, для целей тестирования), где await выражения будет никогда быть неполным, почему вы хотите заставить кого-то написать асинхронный метод без await все равно звонит? Ты ожидал реализации должны быть привязаны к IO, но, возможно, будут особые случаи, когда реализации хотят использовать жестко закодированные данные и т. д.

в основном вам нужно обработать это в документации для метода-если вы не можете доверять исполнителям прочтите это, у вас все равно нет шансов : (


В дополнение к ответу Джона, если вы следуете асинхронный шаблон на основе задач тогда ваши имена методов должны быть suffixed с Async, который самостоятельно документирует, что это асинхронный метод.

Если вы реализуете интерфейс

public interface IFoo
{
    Task BarAsync();
}

это должно быть очевидно, что это должно быть реализовано с async ключевое слово.