我目前正在参与一个将一些旧的 VB6 代码迁移到 C#(.Net Framework 3.5)的项目。我的任务是进行迁移;任何功能增强或重构都将被推到项目的后期阶段。不理想,但你去。
因此,部分 VB6 代码调用了 Windows API SetTimer 函数。我已经迁移了它,但无法让它工作。
迁移的项目构建为 DLL;我创建了一个小型 WinForms 测试工具,它链接到 DLL 并调用相关代码。很简单,就是为了证明调用可以。
迁移后的DLL中相关代码如下:
[DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public extern static int SetTimer(int hwnd, int nIDEvent, int uElapse, AsyncObjectCallerDelegate lpTimerFunc);
public delegate void AsyncObjectCallerDelegate(int hwnd, int uMsg, int idEvent, int dwTime);
static public int StartTimer( AsyncGeoServer.GeoWrapper AsyncObj)
{
m_objGeoWrapper = AsyncObj;
int lngReturn = SetTimer(0, 0, 1, new AsyncObjectCallerDelegate(AsyncObjectCaller));
// When the line below is removed, the call functions correctly.
// MessageBox.Show("This is a temp message box!", "Temp Msg Box", MessageBoxButtons.OKCancel);
return lngReturn;
}
static private void AsyncObjectCaller(int hwnd, int uMsg, int idEvent, int dwTime)
{
// Perform processing here - details removed for clarity
}
static public void StopTimer( int TimerID)
{
try { KillTimer(0, TimerID); }
catch { }
}
上述调用由 DLL 包装在外部 DoProcessing() 方法中;这会在调用 StartTimer(两个 Windows 内核调用)之前使用 CreateEvent 创建一个事件,然后在继续处理之前调用 WaitForSingleObject。AsyncObjectCaller 函数会将事件设置为其执行的一部分,以允许继续处理。
所以我的问题是:如果按照上面列出的方式调用代码,它就会失败。AsyncObjectCaller 回调方法永远不会被触发,并且 WaitForSingleObject 调用超时。
但是,如果我取消注释 StartTimer 中的 MessageBox.Show 调用,它会按预期工作......有点。AsyncObjectCaller 回调方法在调用 MessageBox.Show 后立即触发。我已经尝试将 MessageBox.Show 放在代码中的各个位置,无论我把它放在哪里都是一样的(只要在调用 SetTimer 之后调用它)——回调函数直到消息框被触发显示。
我完全被难住了,对 VB6 或 Windows API 编码都不太熟悉,主要来自 .Net 背景。
谢谢你的帮助!