Я хочу использовать последние асинхронные методы C# 5.0, но каким-то особым образом.
Рассмотрим следующий пример кода:
public abstract class SomeBaseProvider : ISomeProvider
{
public abstract Task Process(SomeParameters parameters);
}
public class SomeConcreteProvider1 : SomeBaseProvider
{
// in this method I want to minimize any overhead to create / run Task
// NOTE: I remove here async from method signature, because basically I want to run
// method to run in sync!
public override Task Process(SomeParameters parameters) {
string result = "string which I don't need any async code to get";
return Task.Run(() => result);
}
}
public class SomeConcreteProvider2 : SomeBaseProvider
{
// in this method, it's OK for me to use async / await
public async override Task Process(SomeParameters parameters) {
var data = await new WebClient().DownloadDataTaskAsync(urlToRequest);
string result = // ... here we convert data byte[] to string some way
return result;
}
}
Теперь, как я собираюсь использовать асинхронные методы (вы можете игнорировать тот факт, что потребитель на самом деле приложение ASP.NET MVC4 в моем случае... это может быть что угодно):
public class SomeAsyncController : AsyncController
{
public async Task SomethingAsync(string providerId)
{
// we just get here one of providers I define above
var provider = SomeService.GetProvider(providerId);
// we try to execute here Process method in async.
// However we might want to actually do it in sync instead, if
// provider is actually SomeConcreteProvider1 object.
string result = await provider.Process(new SomeParameters(...));
return Content(result);
}
}
Как вы можно увидеть, что у меня есть 2 реализации, каждая из которых будет работать по-разному: одну я хочу запускать в асинхронном режиме и не блокировать поток (SomeConcreteProvider2), а другую я хочу иметь возможность запускать синхронно и не создавать никаких объектов Task и т. д. ( который я не могу закодировать в коде выше, т.е. я создаю новую задачу здесь!).
Уже есть такие вопросы, как Как мне синхронно запустить асинхронный метод Task
Итак, вопрос: как организовать мой код (разные сигнатуры методов или разные реализации, или?), чтобы иметь возможность решить, как выполнять метод, и избежать ЛЮБЫХ возможных накладных расходов, вызванных, например, Task.Run(... ) в методе SomeConcreteProvider1.Process?
Обновление 1: очевидные решения (некоторые из них я придумываю в процессе обсуждения), например, добавить какое-то статическое свойство к каждому из провайдеров (скажем, «isAsyncImplementation»), а затем проверить это свойство, чтобы решить, как для запуска метода (с ожиданием или без ожидания в действии контроллера) также есть некоторые накладные расходы: я хочу что-то лучше, если это возможно: D