Dans mon MainWindow
j'ai un bouton qui peut être utilisé pour ouvrir un Process
(appel natif OpenProcess
) et d'effectuer des contrôles sur sa mémoire, mais la méthode appelée sur Click
est asynchrone:A propos Async Tâches et élimination
<Button Content="Attach" Click="OnClickAttach"/>
private async void OnClickAttach(Object sender, RoutedEventArgs e)
{
AttachmentResult result = await m_ViewModel.Attach();
switch (result)
// Different MessageBox depending on the result.
}
maintenant, nous allons voir la partie ViewModel
du code ...
// MemoryProcess class is just a wrapper for Process' handle and memory regions.
private MemoryProcess m_MemoryProcess;
public async Task<AttachmentResult> Attach()
{
AttachmentResult result = AttachmentResult.Success;
MemoryProcess memoryProcess = NativeMethods.OpenProcess(m_SelectedBrowserInstance.Process);
if (memoryProcess == null)
result = AttachmentResult.FailProcessNotOpened;
else
{
Boolean check1 = false;
Boolean check2 = false;
foreach (MemoryRegion region in memoryProcess)
{
// I perform checks on Process' memory regions and I eventually change the value of check1 or check2...
await Task.Delay(1);
}
if (!check1 && !check2)
{
NativeMethods.CloseHandle(memoryProcess.Handle);
result = AttachmentResult.FailProcessNotValid;
}
else
{
// I keep the Process opened for further use. I save it to a private variable.
m_MemoryProcess = memoryProcess;
m_MemoryProcess.Check1 = check1;
m_MemoryProcess.Check2 = check2;
}
}
return result;
}
maintenant ... voilà le problème. Lorsque l'utilisateur ferme l'application, si un Process
est ouvert, je dois fermer correctement son handle. Donc, dans mon MainWindow
je le code suivant:
protected override void OnClosing(CancelEventArgs e)
{
m_ViewModel.Detach();
base.OnClosing(e);
}
Et dans mon ViewModel
je le code suivant:
public void Detach()
{
if (m_MemoryProcess != null)
{
if (m_MemoryProcess.Check1)
// Do something...
if (m_MemoryProcess.Check2)
// Do something...
NativeMethods.CloseHandle(m_MemoryProcess.Handle);
m_MemoryProcess = null;
}
}
La méthode Attach()
peut prendre très longtemps, plus de 2 minutes parfois. Je dois trouver une solution pour les problèmes suivants:
- Si l'utilisateur ferme l'application tandis que la méthode
Attach()
est en cours d'exécution et avantmemoryProcess
est enregistré à la variable privée, la poignéeProcess
ne sera pas fermée. - Si vous enregistrez l'instance MemoryProcess dans la variable privée juste au début de la méthode
Attach()
, l'utilisateur risque d'obtenir unNullReferenceException
s'il ferme l'application alors que la méthodeAttach()
traite sa boucle foreach. - Je ne veux absolument pas que l'utilisateur attende la méthode
Attach()
pour terminer avant de le laisser fermer l'application. C'est horrible.
Comment est-ce que je peux faire ceci?
Que diriez-vous quand ils ferment l'application, si l'appel ASYC n'a pas fini ... il suffit de cacher la fenêtre jusqu'à ce qu'il soit fini, puis fermez l'application réelle quand c'est fait –
C'est aussi étrange parce que la méthode est assez intensive en CPU et si l'application va être fermée quand elle se termine ... bien , à quoi ça sert?! Le mieux serait de l'arrêter complètement ... c'est ce que j'essaie de faire. –
Vous devriez utiliser SafeWin32Handle au lieu de IntPtr pour que vous puissiez vous débarrasser du gestionnaire au lieu de le fermer (ie le GC s'en débarrassera si vous oubliez.) Par exemple: public static extern SafeWin32Handle OpenProcess (int dwDesiredAccess, bool bInheritHandle, int dwProcessId); ' –