C# COM Objects and Multithreading

给你一囗甜甜゛ 提交于 2019-12-23 22:11:40

问题


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

EDIT: Solution

  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.

Thank you guys !!


回答1:


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.

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




回答2:


ApartmentState.STA means:

The Thread will create and enter a single-threaded apartment.

STA have some requirements:

Each single-threaded apartment must have a message loop to handle calls from other processes and apartments within the same process. Single-threaded apartments without objects (client only) also need a message loop to dispatch the broadcast messages that some applications use.

Your main thread and your STA thread are synchronizing with each other via windows messages. If you freeze your STA thread, you may end up freezing your main thread (the main thread is waiting a response from a message sent to STA and the STA does not service it's message loop, thus freezing your GUI). And vice versa. I can't know why is your COM object synchronizing with the main thread, that is something only you can answer.

You should try using an MTA thread, if possible. Not all COM components will work in an MTA.



来源:https://stackoverflow.com/questions/26670370/c-sharp-com-objects-and-multithreading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!