2009-04-18 5 views
0

Je reçois une erreur System.InvalidOperationException lorsque je ferme mon application avant que la recherche ne soit effectuée. Quand je ferme sur Form1_FormClosing je dis à tous mes threads d'abandonner. Dans un thread il a finalisé qui appelle une fonction déléguée qui indique à l'un des contrôles dans le formulaire de changer son texte. Lorsque cela se produit, je reçois l'exception ci-dessus avec "Informations supplémentaires: Invoke ou BeginInvoke ne peut pas être appelé sur un contrôle jusqu'à ce que le handle de fenêtre a été créé."L'interface graphique C# gère les problèmes à la fermeture

Que puis-je faire pour corriger cela? Je pourrais ajouter un indicateur isClosing et le vérifier avant la mise à jour du texte, mais cela ressemble à un hack et masquer le problème. Comment puis-je résoudre cela correctement?

Répondre

1

Cela se produit car le contrôle géré est en cours de suppression et n'a plus de handle, mais vous n'avez pas encore fermé la fenêtre pour que vous la voyiez toujours.

Vous pouvez créer une fonction qui encapsulerait l'appel Invoke et vérifierait IsHandleCreated avant d'appeler Invoke. Si IsHandleCreated est faux, vous ne pouvez pas appeler Invoke et vous pouvez simplement ignorer l'appel.

public static class ControlExtensions 
{ 
    public static TResult InvokeEx<TControl, TResult>(this TControl control, 
              Func<TControl, TResult> func) 
    where TControl : Control 
    { 
    if (!control.IsHandleCreated) 
     return default(T); 

    if (control.InvokeRequired) 
     return (TResult)control.Invoke(func, control); 
    else 
     return func(control); 
    } 

    public static void InvokeEx<TControl>(this TControl control, 
             Action<TControl> action) 
    where TControl : Control 
    { 
    control.InvokeEx(c => { action(c); return c; }); 
    } 
} 

Alors maintenant, juste envelopper les Invoke s de vos discussions avec InvokeEx et il se chargera lorsqu'un contrôle a été et n'a plus une poignée.

this.InvokeEx(c => c.label1.Text = "Hello world"); 
1

Je suis d'accord avec Samuel, mais vérifieriez également IsDisposed:

void Handler() 
{ 
    if (ctrl.IsDisposed || !ctrl.IsHandleCreated) return; 
    if (ctrl.InvokeRequired) 
    Invoke(...); 
    else { 
    ... 
    } 
} 
Questions connexes