2010-06-11 125 views
3

我们正在开发一个软件来控制一个科学的测量设备。它提供了一个COM-Interface定义了几个功能来设置测量参数并在测量数据时触发一个事件。C#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行为有关,但是我没有在这个主题上发现任何东西。

回答

1

什么是客户端和服务器的线程模型 - STA或MTA? (仅供参考 - STA是单线程Com对象,用于允许一次只从一个线程访问其公共方法,MTA是多线程对象,允许从多个线程同时访问其公共方法)

你对他们每个人有多少实例?你如何创建这些实例?我怀疑你只想要一个,但你最后会以多个结束。

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

说明: .NET足够智能,可以检测客户端和服务器是否都受到管理,并且会将COM从图片中提取出来。所以,你的模拟运行纯粹的托管代码。如果你想要正确的测试客户端,你需要把它写成C++(因为我怀疑你的设备控制器是非托管代码)。有关COM线程模型

参考文档:

Understanding and Using COM Threading Models
Processes, Threads and Appartments
Introduction to COM Interop

+0

感谢。我错过了明确地将服务器环路设置为MTA。 – user364676 2010-06-11 16:40:35

+0

当然你想这样做?你的代码不是线程安全的。 – 2010-06-11 16:44:04

1

在您发布的代码中,COM_Sim.client从不分配。有什么遗漏吗?没有看到对象是如何分配的,很难诊断。

此外:您目前有newMeasurementCOM_Sim中声明为公共字段,但newMeasurment(拼写不同)在方法内。正如所写的,这段代码不会编译。您的实际方法中可能存在类似的拼写错误,导致您将其分配给与您认为在NewMeasurement内部创建的对象不同的对象。