Je suis actuellement impliqué dans un projet qui migre un ancien code VB6 vers C# (.Net Framework 3.5). Mon mandat est de juste faire la migration; toute amélioration fonctionnelle ou refactoring doit être poussée vers une phase ultérieure du projet. Pas idéal, mais voilà.Problème avec la méthode de rappel dans l'API SetTimer Windows appelée à partir du code C#
Ainsi, une partie du code VB6 appelle la fonction SetTimer de Windows API. J'ai migré ceci et je n'arrive pas à le faire fonctionner.
Le projet migré est créé en tant que DLL; J'ai créé un petit faisceau de test WinForms qui lie à la DLL et appelle le code en question. Très simple, juste pour prouver que l'appel peut être fait.
le code correspondant dans la DLL migré est la suivante:
[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 { }
}
Les appels ci-dessus sont enveloppés par la DLL dans un procédé DoProcessing() extérieure; Cela crée un événement en utilisant CreateEvent avant d'appeler StartTimer (les deux appels du noyau Windows), puis appelle WaitForSingleObject avant de poursuivre le traitement. La fonction AsyncObjectCaller définira l'événement dans le cadre de son exécution pour permettre au traitement de continuer.
Donc, mon problème est le suivant: si le code est appelé comme indiqué ci-dessus, il échoue. La méthode de rappel AsyncObjectCaller n'est jamais déclenchée et l'appel WaitForSingleObject expire.
Si, cependant, je décommenter l'appel MessageBox.Show dans StartTimer, cela fonctionne comme prévu ... en quelque sorte. La méthode de rappel AsyncObjectCaller est déclenchée immédiatement après l'appel à MessageBox.Show. J'ai essayé de placer MessageBox.Show dans divers endroits dans le code, et c'est la même chose peu importe où je l'ai mis (tant qu'il est appelé après l'appel à SetTimer) - la fonction de rappel ne se déclenche pas jusqu'à ce que la boîte de message affiché.
Je suis complètement perplexe, et aucun n'est trop familier avec le codage API VB6 ou Windows, provenant principalement d'un arrière-plan .Net.
Merci pour toute aide!
Merci pour l'aide ... marquer ce que la réponse puisque c'est la solution que je fini par mettre en œuvre avec succès, et il a donné le plus de détails. – fiveeuros