Стратегии асинхронного вызова синхронных сервисных вызовов в C #

С бизнес-логикой, инкапсулированной за синхронными вызовами служб, например:

interface IFooService
{
    Foo GetFooById(int id);
    int SaveFoo(Foo foo);
}

Как лучше всего расширить / использовать эти вызовы служб в асинхронный способ?

В настоящее время я создал простой класс AsyncUtils:

public static class AsyncUtils
{
    public static void Execute<T>(Func<T> asyncFunc)
    {
        Execute(asyncFunc, null, null);
    }

    public static void Execute<T>(Func<T> asyncFunc, Action<T> successCallback)
    {
        Execute(asyncFunc, successCallback, null);
    }

    public static void Execute<T>(Func<T> asyncFunc, Action<T> successCallback, Action<Exception> failureCallback)
    {
        ThreadPool.UnsafeQueueUserWorkItem(state => ExecuteAndHandleError(asyncFunc, successCallback, failureCallback), null);
    }

    private static void ExecuteAndHandleError<T>(Func<T> asyncFunc, Action<T> successCallback, Action<Exception> failureCallback)
    {
        try
        {
            T result = asyncFunc();
            if (successCallback != null)
            {
                successCallback(result);
            }
        }
        catch (Exception e)
        {
            if (failureCallback != null)
            {
                failureCallback(e);
            }
        }
    }
}

Который позволяет мне вызывать что угодно асинхронно:

AsyncUtils(
     () => _fooService.SaveFoo(foo),
     id => HandleFooSavedSuccessfully(id),
     ex => HandleFooSaveError(ex));

Хотя это работает в простых случаях использования, быстро становится сложно, если другие процессы нужно координировать результаты, например, если мне нужно сохранить три объекта асинхронно, прежде чем текущий поток может продолжиться, тогда мне нужен способ ожидания / присоединения к рабочим потокам.

Параметры, о которых я думал до сих пор, включают:

  • наличие AsyncUtils, возвращающего WaitHandle
  • , при котором AsyncUtils использует AsyncMethodCaller и возвращает IAsyncResult
  • , переписывающий API для включения Begin, Завершите асинхронные вызовы

, например, что-то вроде:

interface IFooService
{
    Foo GetFooById(int id);
    IAsyncResult BeginGetFooById(int id);
    Foo EndGetFooById(IAsyncResult result);
    int SaveFoo(Foo foo);
    IAsyncResult BeginSaveFoo(Foo foo);
    int EndSaveFoo(IAsyncResult result);
}

Есть ли другие подходы, которые мне следует рассмотреть? Каковы преимущества и потенциальные подводные камни каждого из них?

В идеале я хотел бы сохранить простой / синхронный уровень сервиса и предоставить несколько простых в использовании служебных методов для их асинхронного вызова. Мне было бы интересно услышать о решениях и идеях, применимых к C # 3.5 и C # 4 (мы еще не обновились, но сделаем это в относительно ближайшем будущем).

Жду ваших идей.

7
задан chillitom 28 September 2010 в 14:33
поделиться