C# 和本机重叠 I/O

Eri*_*ill 3 c# pinvoke overlapped-io

我有一个正在包装的 C dll,以便可以从 C# 调用它。当状态发生变化时,一个函数使用事件来通知您,并且需要进行一些挖掘才能找到处理它的方法。它似乎工作正常,但我很好奇是否有人比我有更多的经验并且可以提供任何建议。

该函数在 dll 的 .h 文件中定义为:

int NotifyStateChange(OVERLAPPED *overlapped);  
typedef int (*NOTIFY_STATE_CHANGE_PROC)(OVERLAPPED *);  
Run Code Online (Sandbox Code Playgroud)

调用它的示例 C 代码:

OVERLAPPED overlapped;  
overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);  
fns.NotifyStateChange(&overlapped);  
WaitForSingleObject(overlapped.hEvent, INFINITE);  
// ...query for the new state or whatever...
Run Code Online (Sandbox Code Playgroud)

这就是我在 C# 中的处理方式:

[DllImport("myfuncs.dll")]
unsafe public static extern int NotifyStateChange(NativeOverlapped* lpOverlapped);

static private ManualResetEvent m_stateChangeEvent = new ManualResetEvent(false);

public static DeviceState WaitForStateChange()
{
    unsafe
    {
        Overlapped overlapped = new Overlapped(0, 0, 
            m_stateChangeEvent.SafeWaitHandle.DangerousGetHandle(), null);
        IOCompletionCallback callback = StateChangeCallback;
        byte[] userData = new byte[100];
        NativeOverlapped* nativeOverlapped = overlapped.Pack(callback, userData);
        NotifyStateChange(nativeOverlapped);
        m_stateChangeEvent.WaitOne();
        Overlapped.Unpack(nativeOverlapped);
        Overlapped.Free(nativeOverlapped);
    }
    return GetCurrentState();
}

[ComVisibleAttribute(true)]
unsafe static public void StateChangeCallback (
    uint errorCode, 
    uint bytesTransferred, 
    NativeOverlapped* overlapped)
{
    m_stateChangeEvent.Set();
}
Run Code Online (Sandbox Code Playgroud)

我不清楚的一件事是是否需要 userData。NotifyStateChange 只是触发一个事件,它不返回任何数据。将 null userData 传递给 Pack() 似乎工作正常,但我担心 userData 可能在我不知道的情况下发生了一些事情。

如果有更合适的方法来做到这一点,我很感激任何建议。

埃里克

Eri*_*ill 5

啊,是的 - 这正是我向 stackoverflow 提出这些难题的原因。现在看来很明显了。这是简化得多的代码......

    [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();
    }
Run Code Online (Sandbox Code Playgroud)

谢谢!

埃里克