簡體   English   中英

如何僅使用 BroadcastBlock 和 ActionBlock 使用數據流

[英]How To Using Dataflow With Only BroadcastBlock And ActionBlock

這是我在 SO 中的第一個問題,我是使用帶有 BroadcastBlock 和 ActionBlock 的 DataFlow 的新手,我希望我能在這里找到解決方案。 這是結構。

模型

class SampleModel
{
    public string Id { get; set; } = Guid.NewGuid().ToString();
    public bool Success { get; set; } = true;
    public object UniqueData { get; set; }

    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine($"Id - {Id}");
        sb.AppendLine($"Success - {Success}");
        sb.AppendLine($"UniqueData - {UniqueData}");
        string tmp = sb.ToString();
        sb.Clear();
        return tmp;
    }
}

數據流邏輯

class CreateDownloadTask
{
    public async Task VeryLongProcess()
    {
        await Task.Run(async () =>
        {
            Console.WriteLine("Long Process Working..");
            await Task.Delay(TimeSpan.FromSeconds(5));
            Console.WriteLine("Long Process Done..");
        });
    }

    public async Task CreateSimpleBroadcastX<T>(T data)
    {
        Action<T> process = async model =>
        {
            Console.WriteLine("Working..");
            await VeryLongProcess();
            Console.WriteLine("Done");
        };


        var broad = new BroadcastBlock<T>(null);

        var action = new ActionBlock<T>(process);

        var dflo = new DataflowLinkOptions { PropagateCompletion = true };

        broad.LinkTo(action, dflo);

        await broad.SendAsync(data);

        broad.Complete();

        await action.Completion.ContinueWith(async tsk =>
        {
            Console.WriteLine("Continue data");
        }).ConfigureAwait(false);

        Console.WriteLine("All Done");
    }
}

呼叫者

var task = cdt.CreateSimpleBroadcastX<SampleModel>(new SampleModel
{
    UniqueData = cdt.GetHashCode()
});
task.GetAwaiter().GetResult();
Console.WriteLin("Completed");

我希望結果應該是

Working..
Long Process Working..
Long Process Done..
Done
Continue data
All Done
Completed

但我有的是

Working..
Long Process Working..
Continue data
All Done
Completed
Long Process Done..
Done

當 ActionBlock 中有async-await時會發生這種情況。 現在,問題是,在沒有WaitHandle情況下,是否有可能達到我預期的結果?

那就是說,ActionBlock.Completion 會一直等到 ActionBlock 中的ActionDelegate執行完畢?

還是我用那個模式做錯了?

提前致謝,並為我的英語不好而感到抱歉。

你的問題在這里:

Action<T> process = async model => ...

該代碼創建了一個async void方法, 應該避免使用 您應該避免async void的原因之一是因為很難知道該方法何時完成。 這正是正在發生的事情: ActionBlock<T>無法知道您的委托何時完成,因為它是async void

沒有返回值且接受單個參數的異步方法的正確委托類型Func<T, Task>

Func<T, Task> process = async model => ...

現在異步方法返回一個TaskActionBlock可以知道它何時完成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM