0

Good day.

I have a TPL Dataflow mesh for rpc calls

It has two unkinked flows which in simplified way looks like this:

Output flow:

  • BlockBuffer to store output
  • ActionBLock to send output to server and produce sent id

And input flow:

  • while loop to recieve data
  • TransformBlock to parse data
  • BlockBuffer to save answer with sentid

there is a problem: when i make calls from separate threads i can mess with answers, so i need to filter it.

my rpc call:

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));
}

as you can see i have uniqueId which can help me to determine answer for this call, but how can i filter it and await for it?

Is it good way to have some array of buffers (WriteOnceBlock maybe?) which will be created in rpc call and LinkedTo with filter?

i3arnon
  • 113,022
  • 33
  • 324
  • 344
xakpc
  • 1,709
  • 13
  • 27

2 Answers2

0

Ok, i didn't found any proper way so i made a dirty workaround

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;
    }
}
xakpc
  • 1,709
  • 13
  • 27
0

One way to do this would be to create a new block for each id, and link it to the answers block with a predicate checking the id and MaxMessages set to 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();
}
svick
  • 236,525
  • 50
  • 385
  • 514