【发布时间】:2012-04-30 18:04:11
【问题描述】:
我有一些使用单个全局变量的简单 C 代码。显然这不是线程安全的,所以当我使用 P/invoke 从 C# 中的多个线程调用它时,事情就搞砸了。
如何为每个线程单独导入此函数,或使其成为线程安全的?
我尝试声明变量__declspec(thread),但这导致程序崩溃。我也尝试过创建一个 C++/CLI 类,但它不允许成员函数为 __declspec(naked),这是我需要的(我正在使用内联汇编)。我在编写多线程 C++ 代码方面不是很有经验,所以我可能缺少一些东西。
下面是一些示例代码:
C#
[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SomeFunction(int parameter1, int parameter2);
C++
extern "C"
{
int someGlobalVariable;
int __declspec(naked) _someFunction(int parameter1, int parameter2)
{
__asm
{
//someGlobalVariable read/written here
}
}
int __declspec(dllexport) SomeFunction(int parameter1, int parameter2)
{
return _someFunction(parameter1, parameter2);
}
}
[编辑]:SomeFunction() 的结果必须按照基于someGlobalVariable 的规定顺序进行(例如,一个 PRNG,someGlobalVariable 作为内部状态)。因此,不能选择使用互斥锁或其他类型的锁 - 每个线程必须拥有自己的 someGlobalVariable 副本。
【问题讨论】:
-
你多久调用一次 - 如果你不拥有 C 代码,你能在 C# 端进行锁定吗?
-
@SteveTownsend:不,大多数多线程都在调用该函数。
-
必须是全局变量吗?您可以从函数返回状态,并要求在下次调用时将状态传递回函数。 (或指向状态的指针。)
-
尝试在 SomeFunction 上使用 [MethodImpl(MethodImplOptions.Synchronized)] 属性
-
如果你不想放弃全局变量,不想同步方法调用,那么唯一的选择就是真正拥有多个进程(一个全局变量每个地址空间存在一次)。例如,您可以多次启动您的 C# 程序并实现一个 TPL TaskFactory,该任务工厂在此进程池上安排任务。
标签: c# c multithreading pinvoke