Как заставить переопределить дочерние символы async в С# 5.0
Я работаю над системой, в которой ожидается, что несколько клиентских объектов реализуют определенную функцию через интерфейс, и я хочу, чтобы эта функция выполнялась асинхронно с продолжениями (я ожидаю, что реализации будут связаны с I/O-привязкой и хотите, чтобы все клиентские объекты выполнили эту функцию как можно скорее). Я использую Visual Studio Async CTP Refresh для SP1, с С# "5.0".
Какова рекомендуемая практика для обеспечения асинхронного поведения в дочерних объектах моего абстрактного класса (см. ниже)? Я не могу (по-видимому) применять использование методов "async" с использованием подхода виртуального метода. Мне может потребоваться только тип возврата "Задача". Означает ли это, что я не должен пытаться требовать асинхронного поведения вообще в дочерних объектах? В этом случае, если тип возврата будет просто "недействительным"?
Публичный интерфейс является неудачным последствием проектирования системы прямо сейчас, но это отдельная проблема. Очевидно, я не мог сдержать кого-либо асинхронным, который обходит "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 work?
}
}
Ответы
Ответ 1
Является ли метод реализованным с помощью async
/await
или нет, является деталью реализации. Как должен вести себя метод - это детали контракта, которые должны быть указаны обычным способом.
Обратите внимание, что если вы вернете метод Task
или Task<T>
, более очевидно, что он должен быть асинхронным и, вероятно, будет трудно реализовать, не будучи асинхронным.
С другой стороны, если существует реализация (например, для целей тестирования), где выражения await
никогда не будут неполными, почему вы хотите заставить кого-то писать метод асинхронного вызова без вызовов await
? Вы ожидаете, что реализации будут привязаны к IO, но, возможно, будут специальные случаи, когда реализации хотят использовать жестко кодированные данные и т.д.
В основном вы должны обрабатывать это в документации для этого метода - если вы не можете доверять разработчикам, чтобы прочитать это, у вас нет шансов в любом случае: (
Ответ 2
В ответ на ответ Jon, если вы следуете Асинхронный шаблон на основе задач, ваши имена методов должны быть суффиксом Async
, который сам документирует, что это асинхронный метод.
Если вы реализуете интерфейс
public interface IFoo
{
Task BarAsync();
}
должно быть очевидно, что это должно быть реализовано с помощью ключевого слова Async
.