Как предотвратить завершение одного метода события при запуске другого события в C #? - PullRequest
0 голосов
/ 23 мая 2019

Я смотрю на некоторый код платформы, пытающийся решить проблему.

В этой среде есть два метода, управляемых событиями, которые находятся вне нашего контроля.

Мы хотим предотвратить (насколько это возможно) метод «AnalyzeMarket ()», выполняемый при каждом событии закрытия.

Метод AnalyzeMarket () вызывается из метода OnTick (), который происходит каждый раз, когда появляется новая ценаЭто вне нашего контроля.Также вне нашего контроля находится метод Positions_Closed (), потому что мы никогда не знаем, когда позиция будет закрыта, и не можем помешать закрытию позиции.

Основной фрагмент кода, который мы имеем, находится ниже, но не работает 100% времени.Мы понимаем это, потому что мы, очевидно, не будем знать, на что будет обращать внимание процессор.

Пример:

  • Событие закрытия сработало, подпись метода запущена
    • Входит галочка. CPU вызывает AnalyzeMarket.
    • ЦП продолжает выполнять метод AnalyzeMarket за пределами оператора "if"
    • ЦП переключается обратно и теперь устанавливает _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 голосов
/ 23 мая 2019

Я предполагаю, что эти события происходят из разных потоков, что создает для вас гоночные условия.Это самый простой способ, по моему мнению, для обработки этого состояния гонки - это использование 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
   }
}

. Это работает, позволяя только одному потоку одновременно входить вmonitor (lock(sync) {' enters the monitor and leaves it at the corresponding} `. Если один поток имеет блокировку, другой поток блокируется, когда он пытается получить блокировку, пока не получит ее.

Обратите внимание, однако, что если это происходит в том же потоке, вам нужно будет добавить проверку для _wasClosingEventFired так же, как вы это делали изначально, но внутри операторов блокировки.

Также нет, если вы делаете асинхронные ... ждать шаблонов в этих обратных вызовах, вы не можетеuse lock() { } для окружения асинхронных кодов. В этом случае используйте SemaphoreSlim в качестве асинхронного мьютекса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...