Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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# 在分布式系统中组织事件的执行并避免死锁_C#_Algorithm_Events_Synchronization_Priority Queue - Fatal编程技术网

C# 在分布式系统中组织事件的执行并避免死锁

C# 在分布式系统中组织事件的执行并避免死锁,c#,algorithm,events,synchronization,priority-queue,C#,Algorithm,Events,Synchronization,Priority Queue,我对系统中的事件进行优先级排序时遇到问题。 我有一个简单的类,可以订阅彼此的输出 public interface INode<TIn, TOut> : IBaseNode { event EventHandler<TOut> Output; //Note: subscribe just calls node.Output += this.OnInput void Subscribe(IBaseNode node); void OnInp

我对系统中的事件进行优先级排序时遇到问题。 我有一个简单的类,可以订阅彼此的输出

public interface INode<TIn, TOut> : IBaseNode
{
    event EventHandler<TOut> Output; 
    //Note: subscribe just calls node.Output += this.OnInput
    void Subscribe(IBaseNode node);
    void OnInput(object sender, TIn input)
} 
我的问题是,当一个事件发生时,它以一种半不确定的方式发生。我希望维护这些事件的执行顺序,以便以更动态的方式确定事件执行的优先级

我的第一印象是使用优先级较高的队列对任务进行排序,但这可能会导致问题,因为优先级较低的事情可能永远不会执行

public class SynchronizationInfo
{
    public SyncPriority Priority { get; set; } = SyncPriority.Normal;
    public object Sender { get; set; }
    public DateTime Created { get; set; } = DateTime.Now;
    public Task Operation { get; set; }
}

public class SynchronizationContext
{
    public PriorityQueue<SynchronizationInfo> ExecutionQueue = new PriorityQueue<SynchronizationInfo>();
    //...
}
公共类同步信息
{
public SyncPriority Priority{get;set;}=SyncPriority.Normal;
公共对象发送方{get;set;}
创建的公共日期时间{get;set;}=DateTime.Now;
公共任务操作{get;set;}
}
公共类同步上下文
{
public PriorityQueue ExecutionQueue=new PriorityQueue();
//...
}
然而,我仍然难以掌握确保死锁不会发生的方法,如果高优先级的事件以比该优先级执行更快的速度添加,则低优先级的事件将不会执行

此外,仅仅因为某件事情的优先级较低,并不意味着所有优先级较高的事情都应该优先处理,时间是一个重要因素


是否有可靠有效的建议方法来处理任务的优先执行。在某种程度上,任务不会遇到死锁(例如,时间会以较低优先级上移以确保执行的方式增加优先级)?

目前,事件是按照注册顺序执行的。然而,这只是它现在的实现方式,我不建议任何人依赖这种行为,因为在未来的版本中可能不存在这种情况

.NET语言将事件实现隐藏在语法障碍后面,尽管事件处理基于相对明确定义的委托系统

从这里检查委托类:

即使在附加事件之后,也可以通过分离所有处理程序,然后按所需顺序重新附加来更改顺序

注意:您可以通过更改事件上的
add
remove
操作来覆盖事件的默认行为,以指定一些其他行为。然后,您可以将事件处理程序保存在一个列表中,由您自己管理,并根据您喜欢的任何规则处理触发顺序

是否有可靠有效的建议方法来处理任务的优先执行。在某种程度上,任务不会遇到死锁(例如,时间会增加优先级,从而将较低优先级上移以确保执行)

“时间增加优先级”方法的问题是优先级队列需要一直重新计算

让我们回顾一下优先级队列的正常用例。以下是数据结构中已排序项的列表:

  • {Priority=SyncPriority.High,Created=“2021-03-05 12:34:01”,…}
  • {Priority=SyncPriority.High,Created=“2021-03-05 12:34:04”,…}
  • {Priority=SyncPriority.High,Created=“2021-03-05 12:34:06”,…}
  • {Priority=SyncPriority.Normal,Created=“2021-03-05 12:34:02”,…}
  • {Priority=SyncPriority.Normal,Created=“2021-03-05 12:34:05”,…}
  • {Priority=SyncPriority.Low,Created=“2021-03-05 12:34:03”,…}
我们可以从
正常
、,。。。优先。当添加下一个
优先级时,我们可以将其插入具有
正常
优先级的第一个项目之前。数据结构的效率取决于所有其他项的顺序不变这一事实

如果不是创建时间,而是将经过的时间(即增长的时间间隔)添加到混合中,则必须对下一个最高优先级项目的每个请求重新计算顺序。关键点在时间上基本上是线性的,而不是常数

为了避免这个难题及其固有的复杂性,您可以分而治之。允许使用一个窗口系统进行两种简化中的一种

最大优先级队列公开以下成员:

  • 插入
  • RemoveMax
第一个简化示例,对优先级队列中的元素数量进行限制

public class PriorityQueueWithMaxElements
{
私有只读int_MaxElementsPriorityQueue;
私有只读优先队列_PriorityQueue;
专用只读队列_backingQueue;
public PriorityQueueWithMaxElements(int-maxElementsInQueue)
{
_maxElementsInPriorityQueue=maxElementsInQueue;
_priorityQueue=新建priorityQueue();
_backingQueue=新队列();
}
公共作废插入(同步信息)
{
if(_backingQueue.Any()|||_priorityQueue.Count==_maxElementsInPriorityQueue)
{
_backingQueue.Enqueue(信息);
}
其他的
{
_priorityQueue.Insert(信息);
}
}
public SynchronizationInfo RemoveMax()
{
var max=_priorityQueue.RemoveMax();
如果(max==null&&u backingQueue.Count>0)
{
var numberOfItems=Math.Min(_maxementsinpriorityqueue,_backingQueue.Count);
对于(变量i=0;i
第二个示例,对优先级队列中元素之间的最大时间延迟设置一个界限

public class PriorityQueueWithMaxDelay
{
私有只读TimeSpan\u maxDelay;
私有只读优先队列_PriorityQueue;
专用只读队列_backingQueue;
//p中最早项目的日期时间
public class SynchronizationInfo
{
    public SyncPriority Priority { get; set; } = SyncPriority.Normal;
    public object Sender { get; set; }
    public DateTime Created { get; set; } = DateTime.Now;
    public Task Operation { get; set; }
}

public class SynchronizationContext
{
    public PriorityQueue<SynchronizationInfo> ExecutionQueue = new PriorityQueue<SynchronizationInfo>();
    //...
}