C ++ / cli -> вызов c # dll -> вызов проблемы OpenFileDialog - PullRequest
2 голосов
/ 06 июля 2010

Я пишу расширения для программы на C ++. Я пишу стандартные библиотеки C / C ++ и использую IJW для вызова библиотеки C #. Это всегда работало идеально, пока я не написал и не вызвал C # dll, который в свою очередь вызвал OpenFileDialog и SaveFileDialog. Когда бы ни вызывался с ShowDialog, приложение зависало.

Итак, при создании «Минимального рабочего примера» я получил: Произошло необработанное исключение типа «System.Threading.ThreadStateException» в System.Windows.Forms.dll

Дополнительная информация: Для выполнения вызовов OLE текущий поток должен быть переведен в однопотоковый режим (STA). Убедитесь, что на вашей главной функции помечен атрибут STAThreadAttribute. Это исключение возникает только в том случае, если к процессу присоединен отладчик.

Итак, я попытался добавить атрибут STAThread перед основным в моем «Минимальном рабочем примере», и я получил эту ошибку.

ошибка C2337: «STAThread»: атрибут не найден

Итак, два вопроса:

  1. Как d0 я получаю «Минимальный рабочий пример» и
  2. Как мне заставить работать настоящее приложение?

(возможно ли даже добавить атрибут STAThread в неуправляемый блок #pragma?)

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

Ответы [ 2 ]

2 голосов
/ 06 июля 2010

Когда вы DLL, вы не можете напрямую контролировать квартиру, в которой работает ваш поток - поток может находиться только в одной квартире за раз, и поэтому, если поток, который вызывает вашу DLL, уже является другой квартирой, то вы не можете его изменить.

Контролируете ли вы код, который вызывает вашу DLL?Если нет, то я думаю, что лучшее, что вы можете сделать, - это запустить собственный поток (в котором вы можете контролировать квартиру, в которой он работает, через CoInitializeEx (NULL, COINIT_APARTMENTTHREADED) )а затем позвоните OpenFileDialog / SaveFileDialog оттуда.

0 голосов
/ 06 июля 2010

Все

Спасибо за помощь. По какой-то причине мне не пришло в голову начать новую тему.

Спасибо всем за этот лакомый кусочек. Поскольку я уже нахожусь в IJW C ++ / cli, я решил, что лучше решить проблему с помощью .net framework.

Как только я понял, что мне нужна новая тема, это было довольно просто.

Я переместил свою функцию, которая вызывает 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)

...