正确的方法来过滤Block Buffer.ReceiveAsync

时间:2013-08-24 00:56:56

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

美好的一天。

我有一个用于rpc调用的TPL数据流网格

它有两个uninkinked流,简化方式如下:

输出流程:

  • BlockBuffer来存储输出
  • ActionBLock将输出发送到服务器并生成已发送的内容

输入流程:

  • while循环接收数据
  • TransformBlock解析数据
  • BlockBuffer用sentid保存答案

有一个问题:当我从不同的线程拨打电话时,我可以搞砸答案,所以我需要过滤它。

我的rpc电话:

public async Task<RpcAnswer> PerformRpcCall(Call rpccall)
{
    ...
    _outputRpcCalls.Post(rpccall);
    long uniqueId = GetUniq(); // call unique id
    ...
    var sent = new Tuple<long, long>(uniqueId, 0);
    while (_sentRpcCalls.TryReceive(u => u.Item1 == uniqueId, out sent)) ; // get generated id from send function

    return await _inputAnswers.ReceiveAsync(TimeSpan.FromSeconds(30));
}

你可以看到我有uniqueId可以帮助我确定这个电话的答案,但我怎样才能过滤它并等待它呢?

是否有一些好的方法可以在rpc调用中创建一些缓冲区(WriteOnceBlock可能?),并使用filter来创建LinkedTo?

2 个答案:

答案 0 :(得分:0)

好的,我没有找到任何正确的方法,所以我做了一个肮脏的解决方法

while (true)
{
    answer = await _inputAnswers.ReceiveAsync(TimeSpan.FromSeconds(5)); 

    if (answer.Success)
    {
        if (answer.Answer.Combinator.ValueType.Equals(rpccall.Combinator.ValueType))
        {
            break;
        }
        else
        {
            // wrong answer - post it back
            _inputAnswers.Post(answer.Answer);
        }

    }
    else
    {
        // answer fail - return it
        break;
    }
}

答案 1 :(得分:0)

执行此操作的一种方法是为每个id创建一个新块,并将其链接到answers块,并使用谓词检查id并将MaxMessages设置为1:

Task<Answer> ReceiveAnswerAsync(int uniqueId)
{
    var block = new BufferBlock<Answer>();

    _inputAnswers.LinkTo(
        block,
        new DataflowLinkOptions { MaxMessages = 1, PropagateCompletion = true },
        answer => answer.Id == uniqueId);

    return block.ReceiveAsync();
}