C#COM对象和多线程 [英] C# COM Objects and Multithreading

查看:372
本文介绍了C#COM对象和多线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发Windows窗体应用程序,该程序可与串行设备通信.设备的供应商提供了* .dll文件,其中包括进行交互的方法.我在Visual Studio中添加了对* .dll文件的引用.
如果我调用设备库(Get())的函数,则2秒钟后会收到响应.为了避免冻结GUI,我产生了一个新线程,该线程初始化库对象的新实例并调用Get()方法.
但是,调用Get()将GUI冻结2秒钟.似乎该对象已在主线程中初始化.
我不知道我在代码中错过了什么.下面是一段代码,再现了我的问题:

i am currently developing an windows form application, which communicates with a serial device. The vendor of the device offers a *.dll file including methods for interacting. I added a reference to *.dll file in visual studio.
If i call a function of device library (Get()), i get a response after 2 seconds. To avoid freezing my GUI, i spawn a new thread, which initializes a new instance of the library object and calls the Get()-Method.
However, calling Get() freezes my GUI for exactly 2 seconds. It seems like the object is already initialized in the main thread.
I don't know what i missed in my code. Here comes a snippet of code reproducing my problem:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MyDevice deviceObj = new MyDevice();
            Thread myThread = new Thread(new ThreadStart(deviceObj.getValues));

            myThread.IsBackground = true;
            myThread.SetApartmentState(ApartmentState.STA);
            myThread.Start();
        }
    }

    class MyDevice
    {
        public void getValues()
        {

            // initialize object of device library
            Tcddka.tcddk tcd = new Tcddka.tcddk();

            // (comPort, identifier, timeout)
            tcd.Init((Int16)(3 - 1), "deviceID", 7000);

            for (int i = 0; i < 10; i++)
            {
                tcd.Get(); // measure new values
                Thread.Sleep(2000);
            }
        }
    }



预先感谢您的努力,
迈克尔



Thank you in advance for your efforts,
Michael

解决方案

  1. 实施 STAThread ,派生自己的类.覆盖Initialize()(不要忘记调用base.Initialize()并在此处创建您的COM对象)
  2. 我的DLL库未注册.打开命令行,输入 regsvr32您的DLL文件的路径"
  3. 打开注册表,搜索您的DLL文件名,浏览到InprocServer32文件夹并检查 ThreadingModel 设置为Apartment.
  1. Implement STAThread, derive your own class of it. Override Initialize() (don't forget to call base.Initialize() and create your COM Object here)
  2. My DLL-Library wasn't registered. Open command line, type in regsvr32 "path to your DLL file"
  3. Open registry, search for your DLL file name, browse to folder InprocServer32 and check if the ThreadingModel is set to Apartment.

谢谢你们!

推荐答案

我首先要检查COM组件是否具有

I would first check whether the COM component has threading model set in the registry. If the ThreadingModel is not set, the component is created always in the first STA thread. In that case you should contact the component author about this issue. Sure you can set the ThreadingModel to "Apartment" by yourself but I would use it only as temporary fix while waiting the component author to fix the registration.

您仍然必须按照Hans Passant的建议在另一个STA线程中创建组件.

You must still create the component in another STA thread as Hans Passant suggested.

这篇关于C#COM对象和多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆