【问题标题】:How can I await my custom data flow block completion?如何等待我的自定义数据流块完成?
【发布时间】:2020-02-23 05:02:32
【问题描述】:

我正在使用 ITargetBlock,并且已经成功地创建了一个自定义数据流块。但是,我无法全神贯注地实施“完成”任务。我目前将其定义为:

public Task Completion { get; }

一旦我构建了我的数据流线,我就会尝试等待这个完成任务,但会得到一个引用的“空”对象。这是因为我没有将完成任务分配给任何东西。

我应该把它分配给什么?我认为它会自动与数据流块相关联,但默认为空...

我应该将 Completion 分配给什么?

【问题讨论】:

    标签: c# async-await task-parallel-library tpl-dataflow


    【解决方案1】:

    当您实现代码时,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;
            }
            // ...
        }
    }
    

    【讨论】:

    • 这会触发完成任务,这很好!但是,这如何与“传播完成”链接选项结合使用?触发这个补全源会绕过补全传播吗?
    • 不,“传播完成”所做的是,一旦先前的任务状态变为“已完成”,它将在链中的下一个方法上调用 Complete(),作为其自我清理工作的一部分。跨度>
    猜你喜欢
    • 2021-08-21
    • 2011-11-06
    • 1970-01-01
    • 2013-01-08
    • 1970-01-01
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    相关资源
    最近更新 更多