传递信息并从另一个线程通知一个线程的最简单方法

Posted

技术标签:

【中文标题】传递信息并从另一个线程通知一个线程的最简单方法【英文标题】:Simplest way to pass information and notify a thread from another thread 【发布时间】:2013-10-29 09:17:55 【问题描述】:

我有一个 C# 应用程序,它在加载时(在 Windows 上)在新线程上从非托管 C++ DLL 调用函数。此时它们作为并行线程运行并执行不同的任务。 DLL 函数每隔一段时间将一些信息写入内存映射文件。我希望此函数在完成对 MMF 的写入后向 C# 应用程序发送通知。这个通知最好带有一些数字,但如果这使事情复杂化,则不是必须的。

编辑:

在整个过程中发生的情况是 C++ 库正在执行一些繁重的计算任务,而 C# 应用程序是一个用作 GUI 的 WPF 项目,C++ 将其状态更新作为一个很长的向量发送打印到 MMF 的参数(似乎是一种快速且有条理的方式)。此信息应显示在 GUI 中。

在 cmets 中,有人说使用 MMF 在这里不是一个好习惯,因为所有活动都在同一个进程中执行。我愿意就如何更好地规划此程序提出建议。

【问题讨论】:

如果你想要好的建议,我想你需要解释更多。首先,是什么促使您选择内存映射文件? 对我来说,听起来你想将一些信息从一个线程传递到另一个线程,两者都在同一个进程中运行。 @helb 猜你是对的,已编辑 内存映射文件在这里是完全错误的。这是一个进程中的问题。 @DavidHeffernan 我已经编辑了问题的名称和内容,很高兴听到你的意见 【参考方案1】:

您可以将委托作为回调函数传递给非托管函数,以便在完成时通知调用者(C# 应用程序)。

使用这样的 C++ 函数

void SetFinishedCallback(void (*callback)(bool success));

然后使用 C# 导入函数

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void FinishedDelegate([MarshalAs(UnmanagedType.U1)]bool success);

[DllImport("unmanaged.dll")]
private static extern void SetFinishedCallback(FinishedDelegate callback);

你应该可以调用函数

SetFinishedCallback(MyFuncAcceptingBool);

编辑:原则上您可以传递计算的整个结果,而不是传递一个布尔值来指示成功/失败,而不再需要 MMF。这引发了编组问题,因为您必须将数据从非托管代码传递到托管代码。如果您有一个简单的数据结构(例如字节数组),那将很容易。

在 C++ 中使用

void SetFinishedCallback(void (*callback)(void* data, int length));

在 C# 中使用

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void FinishedDelegate(IntPtr data, int length);

您必须在回调方法中手动转换 IntPtr。

【讨论】:

没错。如果您的应用程序正在调用另一个 dll 上的方法,则这两个线程在同一个进程中运行。无需进程间通信。 @RonTeller 编写代码还为时过早。首先你需要决定你使用什么架构。如果您没有正确的架构,就无法编写代码。 这解决了C++ - C#问题,但不是跨线程问题。 @Pete True,但正如 David Heffernan 所说,现在编写代码还为时过早。线程安全的解决方案将在回调函数中实现,具体取决于应用程序设计。

以上是关于传递信息并从另一个线程通知一个线程的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个线程更新 GUI?

如何从另一个线程更新 GUI?

如何从另一个线程更新 GUI?

C#子线程执行完后通知主线程(转)

为 websocket 提升堆栈协程,如何发布函数并从另一个线程恢复

使用 ZeroMQ Socket 时,我可以从一个线程 send() 并从另一个线程发送 recv() 到同一个套接字吗?