私は現在、古いVB6コードをC#(.Net Framework 3.5)に移行するプロジェクトに携わっています。私の使命は、移行を行うことです。機能の強化やリファクタリングは、プロジェクトの後のフェーズにプッシュされます。理想的ではありませんが、そこに行きます。
したがって、VB6コードの一部は、WindowsAPISetTimer関数を呼び出します。これを移行しましたが、動作させることができません。
移行されたプロジェクトはDLLとしてビルドされます。DLLにリンクし、問題のコードを呼び出す小さなWinFormsテストハーネスを作成しました。非常に簡単です。電話をかけることができることを証明するだけです。
移行された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の呼び出し後に呼び出される限り)。コールバック関数は、メッセージボックスがトリガーされるまでトリガーされません。表示されます。
私は完全に困惑しており、主に.Netのバックグラウンドから来ているVB6またはWindowsAPIコーディングにあまり精通していません。
助けてくれてありがとう!