简体   繁体   中英

How to prevent one event method from completing when another event is fired in C#?

I am looking at some framework code trying to resolve an issue.

In this framework, there are two methods that are event driven and beyond our control.

We want to prevent (as much as possible) the "AnalyzeMarket()" method from executing whenever a closing event is fired.

The AnalyzeMarket() method is called from the OnTick() method, which happens every time a new price comes in. This is beyond our control. Also beyond our control is the Positions_Closed() method because we never know when a position will be close and cannot stop a position from being closed.

The basic code snippet we have is below, but doesn't work 100% of the time. We understand this because we obviously won't know what will get the CPU's focus.

Example:

  • The closing event is fired, method signature started
    • A tick comes in. CPU calls AnalyzeMarket.
    • CPU keeps executing AnalyzeMarket method beyond the "if" statement
    • CPU switches back and now sets the _wasClosingEventFired = true
    • Unfortunately, AnalyzeMarket keeps running because the flag was false when it started.

Is there a better to do what we're trying to achieve?

Here's the relevant code snippet:

//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
    }

Thank you.

I am assuming these events are coming in from different threads, which is causing race-conditions for you. This simplest way, in my opinion, to handle this race condition is using Monitors , in the form of lock statements:

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

This works by only allowing one thread at a time to enter the monitor ( lock(sync) {' enters the monitor and leaves it at the corresponding }`. If one thread has the lock, the other thread will block when it tries to obtain the lock until it obtains it.

Note, though, that if these happen on the same thread, you will need to add the check for _wasClosingEventFired just like you had originally, but inside the lock statements.

Also not, if you are doing async...await patterns within the these callbacks, you cannot use lock() { } to surround asynchronous codes. In this case, use a SemaphoreSlim as an asynchronous-friendly mutex.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM