gpt4 book ai didi

c# - 防止 C# 事件对 VB6 代码造成死锁

转载 作者:太空狗 更新时间:2023-10-30 01:24:58 24 4
gpt4 key购买 nike

我创建了一个多线程 C# COM 程序集,我从 VB6 开始使用它。

C#-COM 可以从多个线程触发事件,我创建了一个不可见的 From 对象并使用它在引发事件之前同步所有事件。

if (myForm.InvokeRequired() )
{
delOnMessage myDelegate = new delOnMessage(Message_received);
myForm.Invoke(myDelegate, new object[] { null, null });
}
else
{
RaiseMyEvent();
}

但是,如果 VB6 代码在事件处理程序内部并调用 COM 对象的某些方法,这会产生一个新事件。

Private Sub m_SomeClass_SomeEvent(obj As Variant)
COMobject.SendAnAnswer() ' This produces a new event
End Sub

在那种情况下,事件系统的一部分停止工作,令人惊讶的是,主要的 VB6 应用程序仍然有效。

编辑:更详细
如果 C#-COM 收到一条消息(来自 CAN 总线线程),它会创建一个事件,在某些情况下,VB6 会调用一个创建事件的 C#-COM 方法,此事件也会到达 VB6。
但是随后 CAN-Bus-Thread 似乎被阻塞了,因为没有收到更多消息(直到程序重新启动)。
但可能会发生其他事件。

CAN 总线线程是一个无限循环,用于接收消息和触发事件。

我有两个问题:

我的同步方式是否正确?
是否可以在不修改 VB6 代码的情况下使其正常工作?

最佳答案

I created an invisible From-object

这听起来很麻烦。使用 InvokeRequired 是一种危险的反模式。它对 VB6 尤其致命,它的运行时严重破坏了线程处理。您知道代码是从工作线程调用的,仅使用 InvokeRequired 来验证您用于同步的表单是否处于正确的状态以正确执行此操作:

if (!myForm.InvokeRequired()) {
throw new InvalidOperationException("Synchronization window not created");
}
delOnMessage myDelegate = new delOnMessage(FireMessageReceivedEvent);
myForm.BeginInvoke(myDelegate, new object[] { null, null });

抛出此异常的可能性很大,创建一个不可见的表单并不那么容易。您可以通过读取窗体的句柄属性来强制创建窗体的句柄属性。或者通过覆盖其 SetVisibleCore() 方法来保持表单不可见:

    protected override void SetVisibleCore(bool value) {
if (!this.IsHandleCreated) {
this.CreateHandle();
value = false;
}
base.SetVisibleCore(value);
}

然而,非常重要的是您在主线程上调用此表单的 Show() 方法。如果您在工作线程中创建表单,它仍然无法正常工作。在您的代码中没有简单的方法来检查这一点。使用调试器和 Debug + Windows + Threads 窗口来验证这一点。

最后但同样重要的是,请使用 BeginInvoke() 而不是 Invoke()。这产生死锁的可能性要小得多。这本身可能会导致问题,但是,您的工作线程可能需要被限制以防止它用调用请求淹没主线程。

关于c# - 防止 C# 事件对 VB6 代码造成死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8007484/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com