Реализация классического асинхронного шаблона с использованием TPL - PullRequest
10 голосов
/ 02 марта 2011

Я пытаюсь реализовать собственный TrackingParticipant для WF 4. Я могу написать метод Track, но моя реализация будет медленной.

Как я могу реализовать переопределения Begin / EndTrack с помощью параллельной библиотеки задач (TPL) .NET 4.0? Я смотрел на TPL и традиционное .NET асинхронное программирование , но не уверен, как его применить здесь.

Обратите внимание, что TrackingParticipant является частью .NET и имеет классический асинхронный шаблон, предопределенный с помощью виртуальных методов.

public class MyTrackingParticipant : TrackingParticipant
{
    protected override IAsyncResult BeginTrack(
        TrackingRecord record, TimeSpan timeout,
        AsyncCallback callback, object state)
    {
        // ?
    }

    protected override void EndTrack(IAsyncResult result)
    {
        // ?
    }

    protected override void Track(TrackingRecord record, TimeSpan timeout)
    {
        // synchronous code to be called
    }
}

1 Ответ

18 голосов
/ 02 марта 2011

Это общий шаблон для реализации классической модели программирования APM:

protected override IAsyncResult BeginTrack(TrackingRecord record, TimeSpan timeout, AsyncCallback callback, object state)
{
    Task result = Task.Factory.StartNew(
        (taskState) =>
        {
           // ... your async work here ...
        },
        state);

    if(callback != null)
    {
        result.ContinueWith((t) => callback(t));
    }

    return result;
}

protected override void EndTrack(IAsyncResult asyncResult)
{
   // Call wait to block until task is complete and/or cause any exceptions that occurred to propagate to the caller
   ((Task)asyncResult).Wait();
}

Если бы метод EndXXX вернул результат, вы бы фактически вернули свойство Result Task вместо простого вызова Wait. Например:

protected override int EndAwesomeCalculation(IAsyncResult asyncResult)
{
   // This will block until the result is available and/or cause any exceptions that occurred propagate to the caller
   return ((Task<int>)asyncResult).Result;
}
...