Итак, вы описали, как вы делаете асинхронные вызовы на клиенте, и на самом деле есть еще несколько вопросов, которые я хотел бы задать о том, как вы на самом деле полностью асинхронны, но, похоже, ваш вопрос больше о том, как быть максимально эффективно на стороне обслуживания, верно?
Если вы выполняете длительные или связанные с вводом / выводом операции в своих сервисных операциях, вы абсолютно должны начать использовать поддержку WCF для асинхронных сервисных операций . Теперь есть много способов сделать это, но если вы используете .NET 4.0, нет лучшего способа, чем использовать Task Parallel Library (TPL).
Во-первых, выгружая работу в поток TPL, вы освобождаете потоки ввода / вывода WCF для обработки большего количества вызовов. Таким образом, ваши длительные операции WCF не связывают способность WCF выставлять другие операции.
Во-вторых, TPL по умолчанию использует пул потоков. Вам не нужно беспокоиться о том, что каждая операция раскручивает свой собственный поток и, в конечном итоге, приводит к нехватке ресурсов. TPL также достаточно умен, чтобы распределить работу по всем ядрам на коробке более эффективно, чем вы могли бы сделать сами, не вкладывая значительные средства в написание программного кода.
В-третьих, TPL можно комбинировать с традиционной моделью асинхронного программирования (APM) , так что если вы работаете с такими вещами, как Streams
(сеть или файл), вы можете использовать их BeginRead/Write
методы максимально использовать асинхронный ввод / вывод, который освободит потоки процессора при блокировке чтения / записи. Вы должны делать это, чтобы достичь максимальной эффективности, даже если вы не используете TPL, TPL просто делает это проще.
Вот простой пример того, как вы можете использовать TPL для реализации асинхронной операции службы:
public IAsyncResult BeginSomeLongRunningOperation(string sampleParam, AsyncCallback callback, object asyncState)
{
Task<int> processingTask = Task<int>.Factory.StartNew(
_ =>
{
... perform insanely long running operation here ...
return 42;
},
asyncState);
// If there was a callback, we have to invoke it after the processing finishes
if(callback != null)
{
processingTask.ContinueWith(
_ =>
{
callback(calculationTask);
},
TaskContinuationOptions.ExecuteSynchronously);
}
return processingTask;
}
public int EndSomeLongRunningOperation(IAsyncResult asyncResult)
{
return ((Task<int>)asyncResult).Result;
}