0

我从 WPF 应用程序中的 c# 代码访问 c++ dll 库。从ui线程访问dll时我没有问题。但是我需要 UI 在 c++ dll 的代码运行时做出响应。所以我尝试从另一个线程访问它。但是当我第一次尝试在非 ui 线程中调用相同的函数(我从 ui 线程调用),函数返回但返回值表明函数中存在内部错误。但是,当我从非 ui 线程运行代码一次或两次以上时,它会成功返回一个非错误值。我没有 dll 的源代码,所以我不确定里面发生了什么。

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();
4

1 回答 1

1

它“可能”与线程上使用的 Apartment 模型有关。

您的 UI 线程将使用 STA(单线程单元)模型...它依赖于消息循环进行同步/序列化访问。

BackgroundWorker将使用 MTA(多线程单元)模型。

该 DLL 库中可能有一些代码依赖于在 UI/STA 线程中运行以进行正确同步,例如一些 COM 调用。它有时有效,有时无效的原因可能是由于竞争条件......由于缺乏同步。

可以指定一个线程是一个 STA ......但不是在BackgroundWorker线程上,因为它们是由 a 创建和管理的ThreadPool,并且总是设置为使用 MTA 单元模型,被重用等......和一个线程必须在它开始之前设置它的公寓状态......之后它就无法更改。

因此,改为创建一个新的Thread集合,将其公寓设置为 STA,并泵出一个消息循环。

于 2013-02-05T17:17:13.560 回答