【发布时间】:2016-11-07 14:10:51
【问题描述】:
我面临的挑战是我正在编写一个 WCF 服务,它本质上是多线程的,可以与我知道不是线程安全的 C 库一起工作,而且我无法影响我正在调用的库.我正在调用的库有一个初始化方法来配置硬件和设置回调处理程序。
如果我在控制台应用程序中执行此过程,它运行得非常好,因为它是在单个线程上。
为了克服这些挑战,我创建了一个辅助类,它实现了 IDisposable 来设置硬件、进行调用并希望在完成后自行拆除。
示例帮助类:
public class MyClass
{
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void Setup(ushort var_one, ushort var_two);
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int Initialise(int port_num, int short_timeout, int long_timeout,
TXN_CALLBACK callback);
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GetDeviceStatus();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void TXN_CALLBACK(int size, [MarshalAs(UnmanagedType.LPStr)] string the_data);
private int Setup(ushort var_one, ushort var_two);
{
Setup(var_one, var_two);
int foo= Initialise(0, shorttimeout, longtimeout, txn_callback);
return foo;
}
public MyStruct GetStatus()
{
Setup(0, 0);
return PtrToStruct<MyStruct>(GetDeviceStatus());
}
private static void txn_callback(int size, string the_data)
{
// Do something with the data
}
private static T PtrToStruct<T>(IntPtr ptr)
{
if (ptr == IntPtr.Zero)
{
// Invalid pointer returned
return default(T);
}
return Marshal.PtrToStructure<T>(ptr);
}
}
调用代码(WCF服务):
using (MyClass class = new MyClass())
{
return class.GetStatus();
}
我省略了 IDisposable 代码,因为它已被设置为由 Visual Studio 创建的默认一次性模式。就目前而言,每次我在第一次之后调用 GetStatus 时,它都知道我之前已经调用过它,直到我重新启动应用程序。我希望它每次调用它时都表现得像第一次一样。每次创建帮助程序的实例时,我需要在处置代码中包含什么以完全从头开始?
【问题讨论】:
-
如果 dll 不是线程安全的,那么实现处理模式对内部损坏状态的可能性没有多大帮助。您需要确保只有一个线程通过生成另一个进程或使用多个重命名的 dll 做一些骇人听闻的事情来访问库
-
我尝试使用 lock() 包装所有服务,以便不能从多个线程调用该库,但它似乎是明智的,因为它之前已经被进程使用过。跨度>
标签: c# wcf interop idisposable