2010-12-02 13 views
1

一度ロードしたフォームライブラリ(form1)とプロンプトが表示されたら、他のフォーム(form2)を開くクラスライブラリアセンブリがあります。それぞれのフォームは別々のスレッドで実行されます。これは、各フォームでFlashweaveアプリケーションを実行し、パフォーマンスを向上させるために別々のスレッドで実行する必要があるためです。 Cで書かれた管理されたローダーを使用してライブラリをロードする場合は、すべて動作します。 混在したclr/C++アセンブリを使用してライブラリをロードすると、form2が閉じられたときApplication.Run()は返されず、多くのスタックスレッドが発生します。 Thread.Abort()を使用して強制的にスレッドを中止しようとしましたが、スレッドは中断しません。 私はフォーム1 application.run()を返して、スレッドが停止することができます。 私はまた、form2の代わりにflashwaveオブジェクトを使用せずに単純な空のフォームを開こうとしましたが、それでも戻りません。Application.Run(フォーム)は返さない(System :: Managementを使用した後)

たぶん、問題は、私はいつか取得このメッセージに接続されている:

CLRは60秒間COM コンテキスト0x196ef0にCOMコンテキスト0x197060から を移行することができませんでした。宛先 コンテキスト/アパートメントを所有する スレッドは、非ポンピング待機または 処理中の非常に長い処理 操作 メッセージのいずれかを実行する可能性が最も高いです。この状況は一般的に に悪影響を及ぼし、 は、アプリケーションが 応答しなくなったり、メモリ使用量が になったりすることがあります。この問題を回避する に、すべてのシングル スレッドアパートメント(STA)は が待ちプリミティブに(例えばCoWaitForMultipleHandlesなど) をポンプに使用するスレッドと 日常長い 実行する操作中にメッセージを送り出します。 Form2の開口部について

:スタックスレッドのための

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) 
      { 

      } 
} 

スタックトレース:

[email protected]() + 0x15のバイト[email protected] () + 0x15バイト[email protected]() + 0x36バイト[email protected]() + 0x8eバイト[email protected]() + 0xe2バイトOLE32.DLL CCliModalLoop :: BlockFn()+ 0x96バイト
[email protected]() ! - 0x51b9バイトのMscorwks.dll NT5WaitRoutine()+ます。0x39 バイトのMscorwks.dll MsgWaitHelper() + 0x97バイトのMscorwks.dllスレッド:: DoAppropriateAptStateWait() - !!!!0xf32e5バイトのMscorwks.dllスレッド:: DoAppropriateWaitWorker() + 0x104バイトのMscorwks.dllスレッド:: DoAppropriateWait () + 0x40のバイトのMscorwks.dll!CLREvent :: WaitEx()+ 0x1438a9バイト
のMscorwks.dll!CLREvent ::待って()+ 0x17の バイト
mscorwks.dll!WKS :: GCHeap :: FinalizerThreadWait() + 0xecバイトmscorwks.dll!ReleaseRCWsInCaches()+ 0xe34fdバイト
mscorwks.dll!ReleaseRCWsInCachesNoThrow() + 0x67バイトのMscorwks.dll!スレッド:: CleanupCOMState() + 0x1b8f83バイトのMscorwks.dll!スレッド:: OnThreadTerminate() + 0x46のバイトのMscorwks.dll!DestroyThread()+ 0x3b バイト
mscorwks。 12 @ dllを!ThreadNative :: KickOffThread() + 0xf2バイトのMscorwks.dll!スレッド:: intermediateThreadProc() + 0x46のバイトkernel32.dllの!@ BaseThreadInitThunk() + 0x12にバイト

そのコードについて最初のスレッドが:

を示しています210

NEWS: 最後に、この動作を生成するものを見つけました。 c#ライブラリをインスタンス化する前に、ローダーは.net System :: Managementを使用してCPUシリアルを取得しようとします。そのような部分を削除すると、すべて正常に動作します。

std::string Loader::GetCPUID() 
{ 
    std::string lsCPUID = ""; 
    try 
    { 
     System::Management::ManagementObjectCollection^ moReturn = nullptr; 
     System::Management::ManagementObjectSearcher^ moSearch ; 

     moSearch = gcnew System::Management::ManagementObjectSearcher("Select * from Win32_Processor"); 

     moReturn = moSearch->Get(); 
     for 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; 
} 

ありがとう: これは有罪一部です。

+0

どうT.MyThreadはとNullReferenceExceptionをスローしませんか? – SpeksETC

+0

なぜでしょうか? しかし、あなたはそれをスキップすることができます...私はちょうどスレッドへの参照を提供し、残忍にそれを中止しようとするが、後でそれを追加しましたが、それは動作しません。 – N4rk0

+0

私はいくつかの不慣れな部分をトリムし、FormTableがインスタンス化される部分をトリミングしました...私はそれを編集します。 – N4rk0

答えて

0

を試してみてください。私は新しいAppDomainを作成して、CPUをシリアルに取得し、そのドメインをアンロードして問題を引き起こしていたSystem :: Managementライブラリをアンロードしました。

refのクラスMarshalByRefType:MarshalByRefObjectを 公共{ : //プロキシを経由して、このメソッドを呼び出します。

std::string GetCPUID() 
{ 
    //char * chp = (char *) System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(R671::R671::Value()).ToPointer(); 
    std::string lsCPUID = ""; 
    //return lsCPUID.assign(chp); 
    try 
    { 
     System::Management::ManagementObjectCollection^ moReturn = nullptr; 
     System::Management::ManagementObjectSearcher^ moSearch ; 

     moSearch = gcnew System::Management::ManagementObjectSearcher("Select * from Win32_Processor"); 

     moReturn = moSearch->Get(); 
     for 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) 
    { 
    } 
    AppDomainSetup^ ads = AppDomain::CurrentDomain->SetupInformation; 
    String^ str = String::Format("AppName={0}, AppBase={1}, ConfigFile={2}", 
     ads->ApplicationName, 
     ads->ApplicationBase, 
     ads->ConfigurationFile); 

    char * chp = (char *) System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str).ToPointer(); 
    lsCPUID.assign(chp); 
    return lsCPUID; 
} 

}

class Loader 
{ 
    std::string GetCPUID() 
    { 
     String^ callingDomainName = Thread::GetDomain()->FriendlyName; 

     // Construct and initialize settings for a second AppDomain. 
     AppDomainSetup^ ads = gcnew AppDomainSetup(); 
     ads->ApplicationBase = 
      "file:///" + Assembly::GetExecutingAssembly()->Location; 
     ads->DisallowBindingRedirects = false; 
     ads->DisallowCodeDownload = true; 
     ads->ConfigurationFile = 
      AppDomain::CurrentDomain->SetupInformation->ConfigurationFile; 

     // Create the second AppDomain. 
     AppDomain^ ad2 = AppDomain::CreateDomain("AD #2", 
      AppDomain::CurrentDomain->Evidence, ads); 
     String^ sam = R671::R671::typeid->FullName; 
     // Create an instance of MarshalbyRefType in the second AppDomain. 
     // A proxy to the object is returned. 
     MarshalByRefType^ mbrt = 
      (MarshalByRefType^) ad2->CreateInstanceFromAndUnwrap(
      Assembly::GetExecutingAssembly()->Location, 
       MarshalByRefType::typeid->FullName 
      ); 
     string lsCPUID; 
     //char * chp = (char *) System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(mbrt2->Value()).ToPointer(); 
     lsCPUID = mbrt->GetCPUID(); 
     try 
     { 
      AppDomain::Unload(ad2); 
     } 
     catch (AppDomainUnloadedException^ /*e*/) 
     { 

     } 

     return lsCPUID; 
    } 

    void Load() 
    { 
     //do things 
     std:string cpuid = this->GetCPUID(); 
     //do things 
     //load c# library and open forms 
    } 
} 
0

InvokeRequiredがtrueを返すMTAスレッドからOpenTableを呼び出している可能性があります。そのため、別のSTAスレッドを作成するのではなく、MTAスレッドでApplication.Run()を呼び出します。

は私が最終的に方法を見つけた...代わりに、STAスレッドからApplication.Run()を呼び出す

+0

いいえ、すべてのスレッドはSTAスレッドです。また、そのスレッドはform1のスレッドであるため、MTAスレッドにすることはできません。 – N4rk0

関連する問題