如何在BeginInvoke()中避免竞争条件?

时间:2018-11-23 11:11:10

标签: c# multithreading com begininvoke

我在浏览器框架(CEFSharp)中有一个按钮。如果单击按钮,则可以使用C#方法DoSomething()处理间接单击。 DoSomething()在“主线程”中未被调用。 DoSomething()应该在“主线程”(AutoCAD中的某些功能)中调用_api.CallAnExportedComFunction()_api.CallAnExportedComFunction()是导出的COM函数。要在“主线程”中调用_api.CallAnExportedComFunction(),我正在使用BeginInvoke()_api.CallAnExportedComFunction()不应并行调用。

如果我按一次按钮,一切正常。如果我有时很慢地按下按钮,则一切正常。

如果我连续非常快地按下按钮,将_api.CallAnExportedComFunction()并行调用,但不应并行调用。我尝试在BeginInvoke内使用lock(),但是它不起作用。

那么为什么_api.CallAnExportedComFunction()被并行调用,如何避免呢?为什么在BeginInvoke()竞争条件中具有动作? lock()仅在两个不同线程之间起作用吗?

我正在使用整数ix向上和向下计数。它永远不会达到值2。但是确实可以。如果我用http请求或睡眠代替COM-call _api.CallAnExportedComFunction(),看来我没有竞争条件。

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

输出
  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代码也不是我的,但是如果重要,我可以尝试添加一些代码。

0 个答案:

没有答案