J'écris une application en C#, .NET 3.0 dans VS2005 avec une fonction de surveillance de l'insertion/éjection de divers lecteurs amovibles (disques flash USB, CD-ROM, etc.). Je ne voulais pas utiliser WMI, car il peut parfois être ambigu (par exemple, il peut générer plusieurs événements d'insertion pour un seul lecteur USB), donc je remplace simplement le WndProc de ma mainform pour attraper le message WM_DEVICECHANGE, comme proposé here. Hier, j'ai rencontré un problème quand il s'est avéré que je devrais utiliser WMI de toute façon pour récupérer des détails de disque obscurs comme un numéro de série. Il s'avère que l'appel de routines WMI depuis l'intérieur de WndProc lève le MDA DisconnectedContext. Après quelques recherches, je me suis retrouvé avec une solution de contournement maladroite pour cela. Le code est le suivant:DéconnectedContext MDA lors de l'appel de fonctions WMI dans une application monothread
// the function for calling WMI
private void GetDrives()
{
ManagementClass diskDriveClass = new ManagementClass("Win32_DiskDrive");
// THIS is the line I get DisconnectedContext MDA on when it happens:
ManagementObjectCollection diskDriveList = diskDriveClass.GetInstances();
foreach (ManagementObject dsk in diskDriveList)
{
// ...
}
}
private void button1_Click(object sender, EventArgs e)
{
// here it works perfectly fine
GetDrives();
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_DEVICECHANGE)
{
// here it throws DisconnectedContext MDA
// (or RPC_E_WRONG_THREAD if MDA disabled)
// GetDrives();
// so the workaround:
DelegateGetDrives gdi = new DelegateGetDrives(GetDrives);
IAsyncResult result = gdi.BeginInvoke(null, "");
gdi.EndInvoke(result);
}
}
// for the workaround only
public delegate void DelegateGetDrives();
qui signifie essentiellement la procédure en cours d'exécution liés à WMI sur un thread séparé - mais, en attendant qu'elle se termine.
Maintenant, la question est: pourquoi ça marche, et pourquoi -t-il à être de cette façon? (ou, le fait?)
Je ne comprends pas le fait d'obtenir le MDA DisconnectedContext ou RPC_E_WRONG_THREAD en premier lieu. Comment exécuter la procédure GetDrives()
à partir d'un gestionnaire d'événements de clic de bouton diffère-t-il de l'appel d'un WndProc? Ne se produisent-ils pas sur le même thread principal de mon application? BTW, mon application est complètement mono-thread, alors pourquoi tout d'un coup une erreur se référant à un «mauvais fil»? L'utilisation de WMI implique-t-elle le multithreading et un traitement spécial des fonctions de System.Management?
En attendant j'ai trouvé une autre question liée à ce MDA, c'est here. OK, je peux supposer qu'appeler WMI signifie créer un thread séparé pour le composant COM sous-jacent - mais il ne me vient toujours pas à l'esprit pourquoi aucune magie est nécessaire lorsqu'on l'appelle après avoir appuyé sur un bouton et que do-magic est nécessaire à partir du WndProc.
Je suis vraiment confus à ce sujet et j'apprécierais des éclaircissements à ce sujet. Il y a quelques choses pires que d'avoir une solution et sans savoir pourquoi cela fonctionne:/
Cheers, Aleksander
Même problème ici! J'aimerais qu'il y ait une solution. Je vais ajouter une prime ... peut-être que cela aidera. – Brad