C# COM 跨线程问题

3
我们正在开发一款控制科学测量设备的软件。它提供了一个COM接口,定义了几个函数来设置测量参数,并在测量数据时触发事件。
为了测试我们的软件,我正在实现该设备的模拟。
COM对象运行一个循环,定期触发事件。客户端应用程序中的另一个循环现在应该使用给定的函数设置COM模拟器。
我创建了一个测量参数类,当设置新的测量时将被实例化。
// COM-Object
public class MeasurementParams
{
    public double Param1;
    public double Param2;
}

public class COM_Sim : ICOMDevice
{
    public MeasurementParams newMeasurement;
    IClient client;

    public int NewMeasurement()
    {
        newMeasurment = new MeasurementParam();
    }

    public int SetParam1(double val)
    {
        // why is newMeasurement null when method is called from client loop
        newMeasurement.Param1 = val;
    }

    void loop()
    {
        while(true)
        {
            // fire event
            client.HandleEvent;
        }
    }
}

public class Client : IClient
{
    ICOMDevice server;

    public int HandleEvent()
    {
        // handle this event
        server.NewMeasurement();
        server.SetParam1(0.0);
    }

    void loop()
    {
        while(true)
        {
            // do some stuff...
            server.NewMeasurement();
            server.SetParam1(0.0);
        }
    }
}

两个循环在独立的线程中运行。当调用server.NewMeasurement()时,服务器上的对象被设置为一个新实例。但在下一个函数中,该对象再次为空。在处理服务器事件时执行相同操作,它可以正常工作,因为该方法在服务器线程中运行。如何使其在客户端线程中也能正常工作。
由于客户端需要与真实设备配合使用,因此我不能修改制造商提供的接口。此外,我需要独立设置测量,而不是定期触发事件处理程序。
我认为这个问题与多线程COM行为有关,但我在这个主题上找不到任何信息。
2个回答

1
在您发布的代码中,COM_Sim.client 从未被赋值。是否有遗漏的部分?如果没有看到对象如何被赋值,很难诊断问题。
此外:您当前在 COM_Sim 中将 newMeasurement 声明为公共字段,但在方法内部使用了不同拼写的 newMeasurment。按照现有的写法,这段代码无法编译。可能存在类似的拼写错误,导致您将其分配给与您在 NewMeasurement 内创建的对象不同的对象。

1

客户端和服务器的线程模型是什么 - STA 还是 MTA?(参考 - STA 是单线程 Com 对象,旨在允许一次只有一个线程访问其公共方法,而 MTA 是多线程对象,允许多个线程并发访问其公共方法)

每个实例有多少个,以及如何创建它们?我怀疑你只想要一个,但最终却得到了多个。

你有多少个线程,哪个方法在哪个线程上运行?你如何创建这些线程,它们是否初始化为运行 STA 对象或 MTA?

注意:.NET 足够聪明,可以检测到客户端和服务器是否都是托管的,并将 COM 排除在外。因此,您的模拟正在运行纯托管代码。如果您需要适当的测试客户端,则需要将其编写为 C++(因为我怀疑您的设备控制器是非托管代码)。

关于 COM 线程模型的参考文档:

理解和使用COM线程模型
进程、线程和公寓
COM互操作简介


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接