c# - 如何避免 BeginInvoke() 中的竞争条件?
问题描述
我在浏览器框架(CEFSharp)中有一个按钮。如果我单击按钮,我可以使用我的 C# 方法处理单击间接DoSomething()
。DoSomething()
不在“主线程”中调用。DoSomething()
应该调用_api.CallAnExportedComFunction()
“主线程”(AutoCAD中的一些功能)。_api.CallAnExportedComFunction()
是一个导出的 COM 函数。要调用_api.CallAnExportedComFunction()
我正在使用的“主线程” BeginInvoke()
。_api.CallAnExportedComFunction()
不应并行调用。
如果我按下按钮一次,一切正常。如果我按下按钮有时会非常慢,一切正常。
如果我连续快速按下按钮 _api.CallAnExportedComFunction()
会被并行调用,但它不应该被调用。我尝试lock()
在 BeginInvoke 内部使用,但它不起作用。
那么为什么要_api.CallAnExportedComFunction()
并行调用,我该如何避免呢?为什么 BeginInvoke() 中的动作有竞争条件?是否lock()
仅适用于两个不同的线程?
我正在使用整数 ix 向上和向下计数。它永远不应该达到值 2。但它确实如此。如果我用 http 请求或睡眠替换 COM 调用_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 代码不是我的,但如果它很重要,我可以尝试添加一些代码。
解决方案
推荐阅读
- summernote - 标记自定义
- javascript - jquery判断上传的图片为空时,让其父节点隐藏
- c# - 多项目解决方案“无法加载文件或程序集'System.Web.Mvc,版本 = 5.2.4.0”,未给出项目名称
- python - 连接具有不同行数和列数的两个数据框
- php - 从更多输入单选按钮值中获取总和
- android - Gradle 同步需要很长时间才能完成解决依赖关系
- php - 无法将文件移动到挂载的网络共享文件夹
- postgresql - 如何在 Postgresql 查询中最小化 CTE 的使用
- .htaccess - .htaccess 和多个意外重定向
- c# - 我应该修改实体框架生成的类吗?