我在浏览器框架(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代码也不是我的,但是如果重要,我可以尝试添加一些代码。