2013-02-05 20 views
0

我從WPF應用程序中的c#代碼訪問C++ dll庫。從ui線程訪問dll時,我沒有任何問題。但是我需要在C++ dll的代碼運行時UI才能響應。所以我嘗試從另一個線程訪問它。但是,當我嘗試在非UI線程中第一次調用相同的函數(我通過ui線程調用)時,該函數返回,但返回值指示函數中存在內部錯誤。但是當我從非UI線程運行代碼時,它成功返回一個非錯誤值。我沒有dll的源代碼,所以我不知道里面會發生什麼。在WPF中使用PInvoke與ui/non-ui線程差異

C++函數

UINT32 myfunc1() 

在C#

[DllImport("mydll.dll")] 
public static extern uint myfunc1(); 

我在UI線程如何到達代碼

uint errorCode = myfunc1(); // returns 0 means no error occured 

我在非UI線程如何到達代碼

BackgroundWorker worker = new BackgroundWorker(); 
worker.DoWork += (s, args) => { args.Result = myfunc1(); }; 
// 1st call args.Result is 10 means internal error ocurred 
// 2nd call args.Result is sometimes 0 and sometimes 10 
// 3rd or later calls args.Result is 0 means no error occured 
worker.RunWorkerCompleted += doSth(); 
worker.RunWorkerAsync(); 
+0

什麼是你的問題? –

+0

我想問題是爲什麼第一次在非UI線程中調用dll函數時出現錯誤。 –

回答

1

它可能與線程上使用的Apartment模型有關。

你的UI線程將使用STA(單線程公寓)模型......它依賴於消息循環來進行同步/序列化訪問。你的BackgroundWorker將使用MTA(多線程公寓)模型。

該DLL庫中可能有一些代碼依賴於在UI/STA線程中運行以便進行適當的同步,例如,也許一些COM調用。它有時起作用的原因,有時不起作用的原因可能是由於缺乏同步而導致的競爭條件。

可以指定一個線程是一個STA ...但不在BackgroundWorker線程上,因爲它們是由ThreadPool創建和管理的,並且始終設置爲使用MTA公寓模型,重新使用等。 ...並且線程必須在啓動之前設置它的公寓狀態......之後它不能被更改。

因此改爲創建一個新的Thread將其公寓設置爲STA,並且還泵送一個信息回覆。

+0

這似乎很有可能。公寓模式對任何基於COM的東西都有巨大的影響,特別是。 – JerKimball