C#和本机重叠I/O
我有一个正在包装的C dll,以便可以从C#调用它。其中一个函数使用事件来通知您某个状态发生了变化,而要解决这个问题需要一些挖掘。它似乎工作正常,但我很好奇是否有人比我有更多的经验,可以提供任何建议 该函数在dll的.h文件中定义为:C#和本机重叠I/O,c#,pinvoke,overlapped-io,C#,Pinvoke,Overlapped Io,我有一个正在包装的C dll,以便可以从C#调用它。其中一个函数使用事件来通知您某个状态发生了变化,而要解决这个问题需要一些挖掘。它似乎工作正常,但我很好奇是否有人比我有更多的经验,可以提供任何建议 该函数在dll的.h文件中定义为: int NotifyStateChange(OVERLAPPED *overlapped); typedef int (*NOTIFY_STATE_CHANGE_PROC)(OVERLAPPED *); 调用它的示例C代码: OVERLAPPED ove
int NotifyStateChange(OVERLAPPED *overlapped);
typedef int (*NOTIFY_STATE_CHANGE_PROC)(OVERLAPPED *);
调用它的示例C代码:
OVERLAPPED overlapped;
overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
fns.NotifyStateChange(&overlapped);
WaitForSingleObject(overlapped.hEvent, INFINITE);
// ...query for the new state or whatever...
这就是我在C#中的做法:
我不清楚的一点是对用户数据的需求。NotifyStateChange只触发一个事件,不返回任何数据。将null userData传递给Pack()似乎工作得很好,但我担心userData在我不知道的情况下可能发生了一些事情
如果有更合适的方法,我非常感谢你的建议
Eric似乎DLL设计人员出于任何原因决定使用超链接结构,而他们可以简单地使用事件的简单句柄来发送信号。显然,他们不希望查看重叠结构中的其他字段,因为DLL似乎不使用它来使用重叠数据(指针和偏移量)执行任何类型的I/O操作。因此,在不太了解所述DLL的情况下,您的使用似乎是正确的,您可以传递nil表示数据,传递0表示偏移量 但请记住,这只是一个猜测。如果可能,请联系DLL作者并要求澄清他们忽略指针和偏移量的假设是否正确
顺便说一下,如果您要得到回调,我不会阻止等待状态更改的线程。只需使用回调来处理事件(状态更改),系统的伸缩性就会更好。您已经在阻塞事件句柄,不需要使用重叠类和回调。您只需将NativeOverlapped.EventHandle成员设置为DangerousGetHandle()返回值。DLL将设置事件
另外,将NotifyStateChange的参数声明为ref而不是指针,这样可以避免使用不安全的关键字。啊,是的-这正是我提出这些难题的原因。现在看来很明显。下面是简化的代码
[DllImport("myfuncs.dll")]
public static extern int NotifyStateChange(ref NativeOverlapped lpOverlapped);
public static DeviceState WaitForStateChange()
{
ManualResetEvent stateChangeEvent = new ManualResetEvent(false);
NativeOverlapped nativeOverlapped = new NativeOverlapped();
nativeOverlapped.EventHandle =
stateChangeEvent.SafeWaitHandle.DangerousGetHandle();
NotifyStateChange(ref nativeOverlapped);
stateChangeEvent.WaitOne();
return GetCurrentState();
}
谢谢
Eric那么DLL本身接受重叠结构,并在状态更改时通知其上的hEvent?我可以说这是非常不寻常的。它可以简单地接受一个事件句柄并通知它,而不需要为I/O设计一个结构……是的,是的,是的,是的。我没有写原件。。。
[DllImport("myfuncs.dll")]
public static extern int NotifyStateChange(ref NativeOverlapped lpOverlapped);
public static DeviceState WaitForStateChange()
{
ManualResetEvent stateChangeEvent = new ManualResetEvent(false);
NativeOverlapped nativeOverlapped = new NativeOverlapped();
nativeOverlapped.EventHandle =
stateChangeEvent.SafeWaitHandle.DangerousGetHandle();
NotifyStateChange(ref nativeOverlapped);
stateChangeEvent.WaitOne();
return GetCurrentState();
}