简体   繁体   English

在WPF中使用ui /非ui线程差异的PInvoke

[英]using PInvoke in WPF with ui/non-ui thread difference

I access a c++ dll library from c# code in a WPF application. 我从WPF应用程序中的c#代码访问c ++ dll库。 I have no problems while accessing the dll from the ui thread. 从ui线程访问dll时我没有问题。 But I need the UI to be responsive while the code of the c++ dll is running. 但是我需要UI在C ++ dll的代码运行时响应。 So I try to access it from another thread. 所以我尝试从另一个线程访问它。 But when I try to call the same function (that I call from the ui thread) in a non-ui thread for the first time , the function returns but the return value indicates there is an internal error in the function. 但是,当我第一次尝试在非ui线程中调用同一函数(从ui线程调用) ,该函数返回,但返回值表明该函数存在内部错误。 But when I run the code from a non-ui thread once or twice more , it successfully returns a non-error value. 但是,当我从非ui线程中再次运行代码一次或两次时 ,它会成功返回非错误值。 I don't have the source code of the dll so I am not sure what happens inside. 我没有dll的源代码,所以我不确定内部会发生什么。

c++ function c ++函数

UINT32 myfunc1()

In C# 在C#中

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

How I reach the code in ui thread 我如何在ui线程中找到代码

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

How I reach the code in non-ui thread 我如何在非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();

It "might" have something to do with the Apartment model being used on threads. 它“可能”与线程上使用的Apartment模型有关。

Your UI thread will be using the STA (Single Threaded Apartment) model...it relies on the message loop for synchronization/serializing access. 您的UI线程将使用STA(单线程单元)模型...它依赖于消息循环来进行同步/序列化访问。

Your BackgroundWorker will be using the MTA (Multi-Threaded Apartment) model. 您的BackgroundWorker将使用MTA(多线程单元)模型。

There's probably some code in that DLL library that relies on being run in a UI/STA thread for proper synchronization eg some COM calls perhaps. DLL库中可能有一些代码依赖于在UI / STA线程中运行以进行适当的同步,例如,可能有一些COM调用。 The reason it sometimes works, and sometimes doesn't is probably down to a race condition...due to lack of synchronization. 之所以有时行之有效,有时却行不通的原因可能是由于缺乏同步而造成的。

It's possible to specify that a thread is an STA one....but not on BackgroundWorker threads, because they are created and managed by a ThreadPool and are always set to use the MTA apartment model, get reused, etc....and a Thread must have it's apartment state set before it is started...after which it cannot be changed. 可以指定一个线程是STA线程...。但是不能在BackgroundWorker线程上指定,因为它们是由ThreadPool创建和管理的,并且始终设置为使用MTA单元模型,可以重用,等等。线程必须在启动之前设置好其单元状态,之后才能进行更改。

So instead create a new Thread set its apartment to STA, and also pump a messageloop. 因此,相反,创建一个新的Thread将其单元设置为STA,并添加一个messageloop。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM