如何在C#中触发另一个事件时阻止一个事件方法完成?

时间:2019-05-23 01:04:23

标签: c# events

我正在查看一些试图解决问题的框架代码。

在此框架中,有两种方法是事件驱动的并且不受我们控制。

我们希望尽可能避免触发关闭事件时执行“ AnalyzeMarket()”方法。

从OnTick()方法调用AnalyzeMarket()方法,该方法在每次引入新价格时发生。这是 超出我们的控制范围。另外,Positions_Closed()方法也是我们无法控制的,因为我们永远不知道什么时候该位置 平仓,不能停止平仓。

下面是我们提供的基本代码段,但100%的时间无法正常运行。我们了解这一点,因为我们显然不知道 什么会引起CPU的关注。

示例:

  • 关闭事件被触发,方法签名已开始
    • 出现一个滴答声。CPU调用AnalyzeMarket。
    • CPU继续执行“ if”语句之外的AnalyzeMarket方法
    • CPU切换回去,现在设置_wasClosingEventFired = true
    • 不幸的是,AnalyzeMarket继续运行,因为该标志在启动时为假。

是否有更好的方法来完成我们要实现的目标?

以下是相关代码段:

//Called by the framework whenever someone closes a price position
private void Positions_Closed(PositionClosedEventArgs args)
        {
        //Flag so we don't place any more orders or anything until this method completes
        _wasClosingEventFired = true;

        //other stuff this method does

        //Signal that this method is over with
        _wasClosingEventFired = false;
        }

//This method is called by the framework every time a new price comes in
//This is unpredictable and could be 1ms from "now", 2 seconds from "now", etc.
protected override void OnTick()
        {
            AnalyzeMarket();
        }

private void AnalyzeMarket()
    {
        //Does a few preliminary logging and other set ups

        if (!_wasClosingEventFired)
            {
            //Does the brunt of the work
            //This is the code we want to make sure doesn't
            //run when a closing event happens. If that means
            //we have to wait a few "ticks", that's fine.
        }

        //Clean up stuff
    }

谢谢。

1 个答案:

答案 0 :(得分:0)

我假设这些事件来自不同的线程,这为您带来了竞争条件。我认为,处理这种竞争情况的最简单方法是使用Monitors语句形式的lock

private object sync= new object();
//Called by the framework whenever someone closes a price position
private void Positions_Closed(PositionClosedEventArgs args)
{
   lock (sync) {                 
      //other stuff this method does

   }
}

//This method is called by the framework every time a new price comes in
//This is unpredictable and could be 1ms from "now", 2 seconds from "now", etc.
protected override void OnTick()
{
   AnalyzeMarket();
}

private void AnalyzeMarket()
{
   //Does a few preliminary logging and other set ups
   lock (sync) {               
      //Does the brunt of the work
      //This is the code we want to make sure doesn't
      //run when a closing event happens. If that means
      //we have to wait a few "ticks", that's fine.

      //Clean up stuff
   }
}

这是通过一次只允许一个线程进入监视器(lock(sync) {' enters the monitor and leaves it at the corresponding}`来实现的。如果一个线程具有锁,则另一个线程将在尝试获得锁之前阻塞,直到获得它为止。

但是,请注意,如果这些操作发生在同一线程上,则需要像原来一样在_wasClosingEventFired中添加检查,但要在lock语句中。

此外,如果您在这些回调中执行async ... await模式,则不能use lock() { }包围异步代码。在这种情况下,请使用SemaphoreSlim作为异步友好的互斥量。