2013-02-05 21 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