c# - How we can use COM Object in multithreading environment? -


i working @ winform application works fine com object because use single thread .but system using progressbar load data com object ,here problem starts

  • gui freezed during loading data (data getting com object ) .

  • to solve problem ,i tried use backgroundwork solved problem of freezed gui .but later found backgroundwork use threadpool default create error in com object class because of multithread .i had tried code create single ,but still not working

           thread thread = new thread(() =>          {              firmware_update_access();//it consumes com object         });         thread.setapartmentstate(apartmentstate.sta);         thread.start(); 

    com component dll which creates exception when try run under new thread included (thread.setapartmentstate(apartmentstate.sta) .exception system.invalidcastexception: hresult: 0x80004002 (e_nointerface)). question how can create new sta thread(other ui thread) should able use com object .

so, create, access , dispose managed com wrapper (rcw) in 1 dedicated background thread, i.e. com wrapper access done in thread callback method.

data or method calls have marshalled from/to ui thread.

update:

depending on performance , other requirements, have 2 choices:

  1. encapsulate object creation, 1 or more consecutive method calls (rcw usage) , object disposal in 1 thread call. can use thread pool (e.g. task.factory.startnew()) every com server call. have ensure, 1 thread accesses com server @ same time, otherwise threading issue occurs.
  2. encapsulate object creation, method calls (rcw usage) , object disposal in 1 dedicated background thread. have create signalling mechanism perform com server calls. simple example use enumeration different methods called, queue , event wake-up thread if there pending method call.

example choice 1:

task.factory.startnew(() => {   myrcwtype objserver = null;    try   {     objserver = new myrcwtype(); // create com wrapper object     objserver.mymethodcall1();     objserver.mymethodcall2();   }   catch(exception ex)   {     // handle exception   }     {     if(objserver != null)     {       while(marshal.releasecomobject(objda) > 0); // dispose com wrapper object     }   } }); 

example choice 2:

private enum methodcallenum { none, method1, method2 }; private queue<methodcallenum> _queue = new queue<methodcallenum>(); private autoresetevent _evtqueue = new autoresetevent(false); private object _syncroot = new object();  private thread _myrcwworker; private void cancellationtokensource _cancelsource = new cancellationtokensource();  // maybe in main form protected override void onload(eventargs e) {     base.onload(e);    // create 1 , background thread rcw access   _myrcwworker = new thread(() => dorcwwork(_cancelsource.token, _evtqueue));   _myrcwworker.isbackground = true;   _myrcwworker.start(); }  private void callmethod1() {   enqueue(methodcallenum.method1); }  private void enqueue(methodcallenum m) {   lock(_syncroot)   {     _queue.enqueue(m);   }   _evtqueue.set(); // signal new method call }  private methodcallenum dequeue() {   methodcallenum m = methodcallenum.none;    lock(_syncroot)   {     if(_queue.count > 0)       m = _queue.dequeue();   }         return m; }  private void dorcwwork(cancellationtoken canceltoken, waithandle evtqueue) {   myrcwtype objserver = null;   int waitresult;    try   {     objserver = new myrcwtype(); // create com wrapper object      while (!canceltoken.iscancellationrequested)     {       if(evtqueue.waitone(200))       {         methodcallenum m = dequeue();         switch(m)         {           case methodcallenum.method1:             objserver.mymethodcall1();           break;            case methodcallenum.method2:             objserver.mymethodcall2();           break;         }       }     }   }   catch(exception ex)   {     // handle exception   }     {     if(objserver != null)     {       while(marshal.releasecomobject(objda) > 0); // dispose com wrapper object     }   } } 

this simple example show program flow. can trigger com server calls thread calling enqueue() method, com server accessed dedicated thread.


Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -