2009-10-06 8 views
1

Je développe une application basée sur le plug-in .NET 2.0. Mon application détecte/charge les plug-ins au moment de l'exécution via une inspection System.Reflection des autres assemblys .NET dans un répertoire spécifié. Cela fonctionne très bien. Mon application contient un contrôle PropertyGrid rempli à partir des propriétés [Browsable (true)] présentes dans les plug-ins chargés. Dans ce PropertyGrid, explorables-vrai-propriétés présentent le comportement suivant:.NET: Les types définis par l'utilisateur dans la grille de propriétés provoquent le blocage

  • Propriétés des types primitifs/(Bool, chaîne, etc.) charge et nettoyage correctement
  • Propriétés des types définis par l'utilisateur (comme un plugin côté défini enum) charger correctement et nettoyer correctement lorsque l'utilisateur ne modifie pas puis au moment de l'exécution.
  • Si un utilisateur modifie un type non standard lors de l'exécution (c'est-à-dire change la valeur d'une énumération via PropertyGrid), l'application se bloque à la fermeture. C'est mon problème.

l'aide de Visual Studio .NET 2005 et le réflecteur Red Gate, j'ai pu isoler le suspendre pour le segment de code suivant de Microsoft.Win32.SystemEvents.WindowThreadProc (je travaillais de l'ensemble cru, mais je am 99% sûr que ce soit le bon endroit):

while (flag) 
{ 
    if (UnsafeNativeMethods.MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 100, 0xff, 4) != 0x102) 
    { 
      goto Label_0072; 
    } 
    Thread.Sleep(1); 
    continue; 
    Label_0053: 
    if (msg.message == 0x12) 
    { 
     flag = false; 
     continue; 
    } 
    UnsafeNativeMethods.TranslateMessage(ref msg); 
    UnsafeNativeMethods.DispatchMessage(ref msg); 
    Label_0072: 
    if (UnsafeNativeMethods.PeekMessage(ref msg, NativeMethods.NullHandleRef, 0, 0, 1)) 
    { 
     goto Label_0053; 
    } 
} 

Il semble « drapeau » n'est pas à true, d'où mon programme se trouve dans cette boucle pour toujours. J'ai trouvé quelqu'un avec a similar problem at .NET 247, mais sa solution recommandée:

System.Threading.Thread.CurrentThread.SetApartmentState(Threading.ApartmentState.STA) 

ne semble pas arranger les choses.

Des pensées?

Merci d'avance.

Répondre

3

Assurez-vous que votre point d'entrée pour votre application est marquée [STAThread] - le STAThreadAttribute est la seule façon .NET 2+ pour marquer votre thread d'interface utilisateur comme STA. Le réglage de l'ApartmentState après le démarrage du thread (qui a fonctionné en 1.1) n'est plus une indication valable.

Cela devrait ressembler à:

public class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.Run(new MyMainForm()); 
    } 
} 
+0

Merci!J'ai été capable de résoudre le problème. C'était un peu plus compliqué que ne l'indique votre extrait, mais votre message m'a mis sur la bonne voie. Les complications provenaient du fait que ce code a été écrit dans VB.net (pouah - pas ma décision) donc, par habitude, VB.net a essayé de tout rendre facile en cachant le code (ce qui finit par rendre les choses difficiles). J'ai finalement créé ma propre classe "Starter" et édité manuellement le fichier .vbproj dans Textpad pour l'utiliser. Par défaut, VS voulait utiliser la classe My.Application avec laquelle il était difficile de travailler. Voir ci-dessous pour un extrait complet de Starter.vb – Vincent

+0

C'est en gros la même chose que je disais. L'astuce consiste à ajouter (dans VB.NET). –

+0

Absolument - Je ne suis pas habitué à VB.net et j'ai eu du mal à trouver * Sub Main() qui n'est pas aussi facile à trouver qu'en C#. Merci encore! – Vincent

0

Lookst comme vous avez isolé le problème de manière incorrecte. Le code que vous avez posté est pour une procédure de fenêtre pour une fenêtre invisible utilisée par WinForms pour attraper les messages de la fenêtre système (comme WM_SETTINGCHANGE). Il est exécuté sur un thread différent de votre thread principal, donc il ne devrait pas l'affecter de quelque façon que ce soit. Si vous venez d'attacher le débogueur à votre processus, vous avez probablement le mauvais thread.

Le drapeau est actuellement activé lorsque la fenêtre reçoit WM_QUIT. Cependant, cela ne devrait pas poser de problème, car le thread est également créé en tant que thread d'arrière-plan, ce qui signifie qu'il sera tué quand votre thread principal se terminera - même si le flag n'est pas défini et continue à boucler, t suspendre l'application à la sortie.

(tout ce qui précède est facile à trouver si vous regardez le code source .NET disponible à partir des serveurs sources de débogage MS si vous utilisez VS2008 SP1).

0

Pour la référence de tous ceux qui tombe par hasard à l'avenir:

Friend Class Starter 

<STAThread()> _ 
Shared Sub Main() 
    Application.EnableVisualStyles() 

    Dim client As ClientGUI 
    client = New ClientGUI() 
    Application.Run(client) 

    My.Settings.Save() 
End Sub 
End Class 
+0

Je pense que cela aurait été BEAUCOUP plus facile en C# car l'extrait de Reed aurait pu être utilisé directement. Les formulaires VB.net essaient d'être intelligents en utilisant My.Application comme objet de démarrage, mais le problème est que cela semble déjà avoir un Sub Main() masqué, donc vous ne pouvez pas simplement ajouter les vôtres. – Vincent