2010-07-06 58 views
2

我寫一個C++程序的擴展。我編寫標準的C/C++ dll,並使用IJW調用C#dll。直到我編寫並調用一個C#dll,然後調用一個OpenFileDialog和一個SaveFileDialog,這一直運行得非常完美。無論何時使用ShowDialog調用,該應用程序都會凍結。C++/cli - >調用c#dll - >調用OpenFileDialog問題

所以在製作「最低工作實例」我得到了一個: 型「System.Threading.ThreadStateException」的未處理的異常出現在System.Windows.Forms.dll中

附加信息:當前線程必須是在進行OLE呼叫之前設置爲單線程單元(STA)模式。確保您的Main函數具有標記的STAThreadAttribute。只有在調試器連接到進程時纔會引發此異常。

因此,我試圖在我的「最小工作示例」中添加main的STAThread屬性,我得到了這個錯誤。

錯誤C2337: 'STAThread':屬性未找到

於是,兩個問題:

  1. 如何D0,我得到了 「最低工作實例」 工作和
  2. 怎麼辦我得到真正的應用程序工作?

(它甚至有可能添加STAThread屬性在非託管的#pragma塊?)

#pragma unmanaged 
BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) 
{ 
... 
} 

回答

2

當你是一個DLL不能直接控制你的線程運行公寓 - 一個線程一次只能在一個公寓中,所以如果調用DLL的線程已經是其他公寓,那麼你不能改變它。

你控制調用你的DLL的代碼嗎?如果沒有,那麼我認爲你可以做的最好的是啓動你自己的線程(可以通過控制運行的公寓,通過CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)),然後從那裏撥打OpenFileDialog/SaveFileDialog

+0

比我更更好的答案。 – 2010-07-06 01:09:19

+0

對我來說,使用WPF而不是WinForms,通過在主函數中調用CoInitialize(NULL)來解決類似的問題。在這種情況下,啓動一個新線程並不是必需的(通常也不需要) – 2013-05-06 05:41:44

0

大家,

感謝您的幫助。由於某種原因,我從來沒有想過開始一個新的線程。

謝謝大家對於那個珍聞。由於我已經在IJW C++/cli land中,我認爲使用.net框架解決問題更好。

一旦我意識到我需要一個新的線程,它非常簡單。

我感動我的函數調用C#DLL到一個單獨的類:

引用類StaClass { 市民:

System::String^ strFile; 
System::String^ strNote; 

void CallWiki() 
{ 
    WikiNotes::FrmWiki fw; 

    fw.File = strFile; 
    fw.Note = strNote; 

    fw.ShowDialog(); 
} 

};

然後從主線程我用這個代碼來啓動一個STA線程。

wiki->strFile = gcnew System::String(File); 
wiki->strNote = gcnew System::String(Note); 

ThreadStart^ threadDelegate = gcnew ThreadStart(wiki, &StaClass::CallWiki); 
Thread^ newThread = gcnew Thread(threadDelegate, 0); 
newThread->SetApartmentState(ApartmentState::STA); 
newThread->Start(); 

簡單,易於閱讀和理解(至少對我來說 - 我是一個程序員的.Net,我從來沒有深入研究多爲COM,MFC和ATL)