C ++ / cli - >调用c#dll - >调用OpenFileDialog问题

时间:2010-07-06 00:55:30

标签: c# c++-cli interop

我编写了C ++程序的扩展。我编写标准的C / C ++ dll,我使用IJW来调用C#dll。这一直很有效,直到我编写并调用了一个C#dll,后者又称为OpenFileDialog和SaveFileDialog。无论何时使用ShowDialog调用,应用程序都会冻结。

因此,在制作“最低工作范例”时,我得到了: System.Windows.Forms.dll中发生未处理的“System.Threading.ThreadStateException”类型异常

附加信息:在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式。确保您的Main函数标记了STAThreadAttribute。仅当调试器附加到进程时才会引发此异常。

所以,我尝试在我的“最小工作示例”中添加main的STAThread属性,我收到了这个错误。

  

错误C2337:'STAThread':找不到属性

所以,有两个问题:

  1. d0如何使“最低工作示例”正常工作
  2. 如何让真正的应用运行起来?
  3. (甚至可以在#pragma非托管块中添加STAThread属性吗?)

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

2 个答案:

答案 0 :(得分:2)

当你是一个DLL时,你不能直接控制你的线程运行的公寓 - 一个线程一次只能在一个公寓里,所以如果调用你的DLL的线程已经是其他公寓,那么你就无法改变它。

您是否控制调用DLL的代码?如果没有,那么我认为你能做的最好的事情就是启动自己的线程(你可以通过CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) 控制它运行的公寓),然后调用{{1从那里开始/ OpenFileDialog

答案 1 :(得分:0)

每个人,

感谢您的帮助。出于某种原因,我从未想过开始新的线程。

感谢大家的那一点。由于我已经在IJW C ++ / cli土地,我认为使用.net框架解决问题会更好。

一旦我意识到我需要一个新线程,这很简单。

我将调用C#dll的函数移动到一个单独的类中:

ref class 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)