c# - Application.Run(form) never returns (after using System::Management) -
i have class library assembly once loaded opens 1 form (form1) , when prompted form1 opens other forms(form2). each form runs in separate thread , because in each form runs flashweave applicatin , performance need run them in separate theads. if load library using managed loader written in c# works ok. if load library using mixed clr/c++ assembly , when form2 gets closed application.run() dooesn't return resulting in many stuck threads. tried force abort threads using thread.abort() still thread doesn't abort. if close form1 application.run() returns , it's thread can stop. tried open simple empty forms instead of form2 without flashwave object in them , , still doesn't return.
maybe problem connected message sometime:
the clr has been unable transition com context 0x197060 com context 0x196ef0 60 seconds. thread owns destination context/apartment either doing non pumping wait or processing long running operation without pumping windows messages. situation has negative performance impact , may lead application becoming non responsive or memory usage accumulating continually on time. avoid problem, single threaded apartment (sta) threads should use pumping wait primitives (such cowaitformultiplehandles) , routinely pump messages during long running operations.
about form2 opening:
private void opentable() { if (!this.invokerequired) { thread tablerun = new thread(new threadstart(opentable)); tablerun.apartmentstate = apartmentstate.sta; tablerun.isbackground = false; tablerun.name = "t2"; tablerun.start(); return; } try { formtable t = new formtable(; t.mythread = thread.currentthread; application.run(t); } catch (exception ex) { } }
stack trace stuck thread:
ntdll.dll!_zwwaitformultipleobjects@20() + 0x15 byte ntdll.dll!_zwwaitformultipleobjects@20() + 0x15 byte kernelbase.dll!_waitformultipleobjectsex@20() + 0x36 byte kernel32.dll!_waitformultipleobjectseximplementation@20() + 0x8e byte user32.dll!_realmsgwaitformultipleobjectsex@20() + 0xe2 byte ole32.dll!cclimodalloop::blockfn() + 0x96 byte
ole32.dll!_cowaitformultiplehandles@20() - 0x51b9 byte mscorwks.dll!nt5waitroutine() + 0x39 byte mscorwks.dll!msgwaithelper() + 0x97 byte mscorwks.dll!thread::doappropriateaptstatewait() - 0xf32e5 byte mscorwks.dll!thread::doappropriatewaitworker() + 0x104 byte mscorwks.dll!thread::doappropriatewait() + 0x40 byte mscorwks.dll!clrevent::waitex() + 0x1438a9 byte
mscorwks.dll!clrevent::wait() + 0x17 byte
mscorwks.dll!wks::gcheap::finalizerthreadwait() + 0xec byte mscorwks.dll!releasercwsincaches() + 0xe34fd byte
mscorwks.dll!releasercwsincachesnothrow() + 0x67 byte mscorwks.dll!thread::cleanupcomstate() + 0x1b8f83 byte mscorwks.dll!thread::onthreadterminate() + 0x46 byte mscorwks.dll!destroythread() + 0x3b byte
mscorwks.dll!threadnative::kickoffthread() + 0xf2 byte mscorwks.dll!thread::intermediatethreadproc() + 0x46 byte kernel32.dll!@basethreadinitthunk@12() + 0x12 byte
regarding code shows first thread is:
//c++ code assembly::form^ f= gcnew assembly::form() ; f->load(); gcroot<assembly::form^>* dsa3_gc_p= new gcroot<assembly::form^>(f); this->obmainlib = (void *)dsa3_gc_p; //------------------------ //the c++ loader calls load() method //c#library public void load() { formthread = new thread(new threadstart(this.start)); formthread.name = "t7"; formthread.isbackground = true; formthread.setapartmentstate(apartmentstate.sta); formthread.start(); } private void start() { config = globalconfig.getconfig(globalconfig.configurationfile); httpinterface = new dhttpinterface(config); lobby = new formlobby(httpinterface, false); workerthread = new thread(new threadstart(this.start)); workerthread.name = "t6"; workerthread.isbackground = true; workerthread.apartmentstate = apartmentstate.sta; workerthread.start(); application.run(lobby); config.savetodisk(); }
news: i've found generate behaviour. before instantiating c# library, loader try cpu serial using .net system::management, if remove such part works ok. guilty part:
std::string loader::getcpuid() { std::string lscpuid = ""; try { system::management::managementobjectcollection^ moreturn = nullptr; system::management::managementobjectsearcher^ mosearch ; mosearch = gcnew system::management::managementobjectsearcher("select * win32_processor"); moreturn = mosearch->get(); each ( system::management::managementobject^ mo in moreturn ) { char * chp = (char *) system::runtime::interopservices::marshal::stringtohglobalansi(mo["processorid"]->tostring()).topointer(); lscpuid.assign(chp); } } catch(system::exception^ ex ) { } return lscpuid; }
thanks.
is possible calling opentable mta thread, invokerequired returns true, therefore instead of creating sta thread, goes straight calling application.run() on mta thread?
try calling application.run() sta thread instead...
Comments
Post a Comment