Как я могу дождаться завершения моего пользовательского блока данных? - PullRequest
2 голосов
/ 23 февраля 2020

Я работаю с ITargetBlock и несколько успешно создал пользовательский блок потока данных. Тем не менее, я не могу обернуться вокруг реализации задачи «Завершение». В настоящее время я определяю это как:

public Task Completion { get; }

Как только я строю свою линию потока данных, я пытаюсь дождаться выполнения этой задачи завершения, но получаю ссылку на «нулевой» объект. Это связано с тем, что я не назначаю задачу завершения чему-либо.

Что мне назначить? Я бы подумал, что он будет автоматически связан с блоком потока данных, но по умолчанию он ничего не значит ...

Что я должен назначить Завершение?

1 Ответ

3 голосов
/ 23 февраля 2020

Когда вы реализуете свой код, Completion должен завершиться после того, как вы вызвали Complete(), и вся работа "в полете" завершена.

Это можно сделать с помощью TaskCompletionSource

public Example<TInput>() : ITargetBlock 
{
    private TaskCompletionSource<Object> tcs = new TaskCompletionSource<Object>()
    public Task Completion { get; }

    public Example()
    {
        Completion = tcs.Task;
    }

    public void Complete()
    {
        // We run this on a background thread because we don't want the call to Complete be blocking.
        Task.Run(() => {
            // Wait here for any currently executing async work your dataflow block does to finish.
            // ...

            tcs.TrySetResult(null);
        }
    }

    public void Fault (Exception exception)
    {
        // Cancel here any running work.
        // ...

        tcs.TrySetException(exception);
    }

    public DataflowMessageStatus OfferMessage(DataflowMessageHeader messageHeader, TInput messageValue, ISourceBlock<in TInput> source, bool consumeToAccept)
    {
        if (Completion.IsCompleted)
        {
            return DataflowMessageStatus.DecliningPermanently;
        }
        // ...
    }
}
...