Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# TPL数据流两阶段提交_C#_.net_Dataflow_Tpl Dataflow_Bufferblock - Fatal编程技术网

C# TPL数据流两阶段提交

C# TPL数据流两阶段提交,c#,.net,dataflow,tpl-dataflow,bufferblock,C#,.net,Dataflow,Tpl Dataflow,Bufferblock,我想实现类似于两阶段提交协议的东西来消费消息 为此,我自己实现了ITargetBlock public class Worker : ITargetBlock<Message> { // Is connected to remote server // Maintaining connection removed for brevity in this example private bool _isConnectionAlive; priva

我想实现类似于两阶段提交协议的东西来消费消息

为此,我自己实现了
ITargetBlock

  public class Worker : ITargetBlock<Message>
  {
    // Is connected to remote server
    // Maintaining connection removed for brevity in this example
    private bool _isConnectionAlive;
    private readonly ActionBlock<MessageWithSource> _action;

    public Worker()
    {
      _action = new ActionBlock<MessageWithSource>(DoWork);
    }

    public DataflowMessageStatus OfferMessage(
      DataflowMessageHeader messageHeader, Message messageValue,
      ISourceBlock<Message> source, bool consumeToAccept)
    {
      if (consumeToAccept || source == null)
      {
        return DataflowMessageStatus.Declined;
      }

      if (!_isConnectionAlive)
      {
        return DataflowMessageStatus.Postponed;
      }

      var reservedMessage = source.ReserveMessage(messageHeader, this);
      if (reservedMessage)
      {
        _action.Post(new MessageWithSource(messageValue, source, messageHeader));
      }

      return DataflowMessageStatus.Postponed;
    }

    // Other methods removed for brevity

    private async Task DoWork(MessageWithSource value)
    {
      try
      {
        // sending message to the server removed for brevity


        // commit that we finished processing without error
        var message = value.SourceBlock.ConsumeMessage(value.MessageHeader, this, out _);

        if (message != value.Message)
        {
          // In which cases can we get here?
          throw new InvalidOperationException("Consumed some other message... oh my");
        }
      }
      catch (WebSocketException)
      {
        // Release reservation if we can't finish work, so other Workers can pickup this message and process it
        value.SourceBlock.ReleaseReservation(value.MessageHeader, this);
      }
    }

    private class MessageWithSource
    {
      public Message Message { get; }
      public ISourceBlock<Message> SourceBlock { get; }
      public DataflowMessageHeader MessageHeader { get; }
    }
  }
公共类工作程序:ITargetBlock
{
//已连接到远程服务器
//在本例中,为了简洁起见,删除了维护连接
私人楼宇与外界的联系仍然活跃;
私有只读操作块_操作;
公职人员()
{
_动作=新动作块(定位销);
}
公用数据流消息消息的状态(
DataflowMessageHeader消息头,消息值,
ISourceBlock源,bool consumeToAccept)
{
if(consumeToAccept | | source==null)
{
返回DataflowMessageStatus。已拒绝;
}
如果(!\u断开连接活动)
{
返回DataflowMessageStatus。已推迟;
}
var reservedMessage=source.ReserveMessage(messageHeader,this);
如果(保留消息)
{
_action.Post(newmessagewithsource(messageValue、source、messageHeader));
}
返回DataflowMessageStatus。已推迟;
}
//为简洁起见,删除了其他方法
专用异步任务DoWork(MessageWithSource值)
{
尝试
{
//为简洁起见,已删除向服务器发送消息的操作
//确认我们完成了处理,没有错误
var message=value.SourceBlock.ConsumeMessage(value.MessageHeader,this,out);
if(message!=value.message)
{
//在什么情况下我们能到这里?
抛出新的InvalidOperationException(“消耗了一些其他消息…哦,天哪”);
}
}
捕获(WebSocketException)
{
//如果我们无法完成工作,请释放保留,以便其他工作人员可以接收此消息并处理它
value.SourceBlock.ReleaseReservation(value.MessageHeader,this);
}
}
私有类MessageWithSource
{
公共消息{get;}
公共ISourceBlock源块{get;}
公共数据流消息头消息头{get;}
}
}
在中,它表示
ConsumeMessage
可以返回与以前提供的不同的实例


我想知道它是在什么情况下发生的,以什么方式发生的?

@StephenCleary如果您能看看为什么在数据流中使用事务语义,更不用说两阶段提交了,我会非常感激的?涉及哪些交易协调人?处理问题的数据流方法是将失败消息或错误消息重定向到另一个块,例如使用
LinkTo()
中的谓词。这样可以避免阻塞输入队列中的其他消息。如果消息被包装在一个“信封”中,表明这是一条好消息还是“坏消息”,则重定向会变得容易得多。信封可以包含重试计数,以确保同一消息不会无限期重试。@PanagiotisKanavos我需要事务语义,因为我需要确保排序,并且其中一些
Worker
实例可能会中断一段时间。可能还有另一种好方法吗?您描述的是排队、发送消息和重试。它与事务语义无关。事务语义意味着要么所有服务器接受并提交操作,要么所有服务器放弃操作。“2PC就是这样做的。@如果您能看看为什么在数据流中使用事务语义,更不用说两阶段提交了,StephenCleary会非常感激的。”?涉及哪些交易协调人?处理问题的数据流方法是将失败消息或错误消息重定向到另一个块,例如使用
LinkTo()
中的谓词。这样可以避免阻塞输入队列中的其他消息。如果消息被包装在一个“信封”中,表明这是一条好消息还是“坏消息”,则重定向会变得容易得多。信封可以包含重试计数,以确保同一消息不会无限期重试。@PanagiotisKanavos我需要事务语义,因为我需要确保排序,并且其中一些
Worker
实例可能会中断一段时间。可能还有另一种好方法吗?您描述的是排队、发送消息和重试。它与事务语义无关。事务语义意味着要么所有服务器接受并提交操作,要么所有服务器放弃操作。他们是如何做到这一点的。