Как избежать условий гонки в BeginInvoke ()? - PullRequest
0 голосов
/ 23 ноября 2018

У меня есть кнопка в рамке браузера (CEFSharp).Если я нажимаю кнопку, я могу обработать косвенный щелчок с помощью моего метода C # DoSomething().DoSomething() не вызывается в "Main-Thread".DoSomething() должен вызывать _api.CallAnExportedComFunction() в «Main-Thread» (некоторые функции в AutoCAD)._api.CallAnExportedComFunction() является экспортированной функцией COM.Для вызова _api.CallAnExportedComFunction() в «Главной теме» я использую BeginInvoke()._api.CallAnExportedComFunction() не следует вызывать параллельно.

Если я нажимаю кнопку один раз, все работает правильно.Если я нажимаю кнопку несколько раз очень медленно, все работает правильно.

Если я нажимаю кнопку очень быстро подряд, вызывается _api.CallAnExportedComFunction() параллельно, но это не должно.Я пытался использовать lock() внутри BeginInvoke, но он не работает.

Так почему же _api.CallAnExportedComFunction() вызывается параллельно и как я могу избежать этого?Почему действие в условиях гонки BeginInvoke ()?Работает ли lock() только между двумя РАЗНЫМИ потоками?

Я использую целое число ix, чтобы считать вверх и вниз.Оно никогда не должно достигать значения 2. Но это так.Если я заменю COM-вызов _api.CallAnExportedComFunction() запросом http или режимом сна, мне кажется, что у меня нет условий гонки.

private object _lock = new object();
private int ix = 0;

private void DoSomething()
{

    System.Diagnostics.Debug.WriteLine($"ThreadAny: {System.Threading.Thread.CurrentThread.ManagedThreadId}");

    // When initializing the Plugin _uiDispatcher.Dispatcher is set to System.Windows.Threading.Dispatcher.CurrentDispatcher
    _uiDispatcher.Dispatcher.BeginInvoke(new Action(() =>
    {
        lock (_lock)
        {
            ++ix;
            System.Diagnostics.Debug.WriteLine($"+ThreadMainBeginInvoke: {System.Threading.Thread.CurrentThread.ManagedThreadId} => ix={ix}");

            _api.CallAnExportedComFunction();

            //System.Threading.Thread.Sleep(1000);

            //var client = new System.Net.WebClient();
            //var b = client.DownloadData("http://www.google.de");

            --ix;
            System.Diagnostics.Debug.WriteLine($"-ThreadMainBeginInvoke: {System.Threading.Thread.CurrentThread.ManagedThreadId} => ix={ix}");

        }
    }), null);
}

OUTPUT :
ThreadAny: 19
+ ThreadMainBeginInvoke: 1 => ix = 1
-ThreadMainBeginInvoke: 1 => ix = 0
ThreadAny: 9
+ ThreadMainBeginInvoke: 1 => ix = 1
ThreadAny:27
+ ThreadMainBeginInvoke: 1 => ix = 2
-ThreadMainBeginInvoke: 1 => ix = 1

К сожалению, я не являюсьCOM-эксперт, и COM-код не мой, но если это важно, я могу попробовать добавить код.

...