Реализация классического асинхронного шаблона с использованием TPL

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

Как я могу реализовать переопределения Begin / EndTrack с помощью библиотеки параллельных задач .NET 4.0 (TPL)? Я просмотрел 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
    }
}

person TrueWill    schedule 01.03.2011    source источник


Ответы (1)


Это общий шаблон для реализации классической модели программирования 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;
}
person Drew Marsh    schedule 02.03.2011
comment
Спасибо! Это работает; как ни странно, рабочий процесс все еще блокируется до завершения Track (). (Он вызывает методы Begin / End.) Похоже, мне пришлось бы реализовать очередь, чтобы получить желаемое поведение. (Чтобы не отвлекать от вашего правильного ответа!) - person TrueWill; 02.03.2011