2010-09-02 5 views
0

Pour quelles raisons this.InvokeRequired est égal à False au sein de InitUIState(), car ce nouveau thread est en cours de création via un délégué?Pourquoi InvokeRequired = False via Delegate.BeginInvoke?

Mon problème est que mon étiquette n'est jamais définie et this.BeginInvoke() ne s'exécute jamais, j'imagine que c'est dû au fait InvokeRequired = False.

private delegate void BackgroundOperationDelegate(ViewMode mode); 
    private BackgroundOperationDelegate backgroundOperationDelegate; 

    private void FormControlPanel_Load(object sender, EventArgs e) 
    { 
     Init(); 
    } 

    private void Init() { 
     this.backgroundOperationDelegate = this.InitUIState; 
     this.backgroundOperationDelegate.BeginInvoke(mode, null, null); 
    } 

    private void InitUIState(ViewMode mode) 
    { 
     // .. other business logic only here relevant 
     // to the worker process .. 
     this.BeginInvoke((MethodInvoker)delegate 
     { 
      this.labelProgramStatus.Text = CONSOLE_IDLE_STATUS; 
     }); 
    } 

J'utilise encore cette fois de modèle et le temps, mais pour une raison quelconque, cette fois il n'est pas l'exécution: P (et oui il n'y a qu'une seule instance de InitUIState() jamais appelé, qu'être du délégué)

Merci les gars.

Images deux fils distincts de vérification:
http://imgur.com/mq12Wl&X5R7G
http://imgur.com/mq12W&X5R7Gl

Suivi question: Est-ce une façon de créer des fils non privilégiées? Je l'ai toujours trouvé si simple et léger. Peut-être que je devrais utiliser thread.Start() et j'éviterai ces problèmes?

+0

S'il vous plaît montrer plus de code. Est-ce Windows Forms? Quand Init() est-il appelé? –

+0

Jon, je suis honoré de votre présence! Ceci est une application Windows Forms, Init() est dans la routine Form_Load(). Matière à réflexion cependant, la forme sur laquelle les étiquettes changent est actuellement invisible (this.Visible = Faux), la raison en est qu'une procédure dans laquelle il a été appelé via un autre formulaire pour mettre à jour l'interface utilisateur, le formulaire sera alors s'affiche avec l'interface utilisateur la plus récente lorsque l'utilisateur double-clique sur ce formulaire dans la barre d'état système pour l'afficher à l'écran. – GONeale

+1

@GONeale: Il est probablement acceptable qu'il soit invisible, mais la poignée GDI a-t-elle été créée? Sinon, cela pourrait expliquer pourquoi InvokeRequired est faux - il n'est peut-être pas encore prêt. Que se passe-t-il si vous essayez de le placer dans le gestionnaire d'événements HandleCreated à la place? –

Répondre

2

Votre 2nd BeginInvoke lancera une exception.

Essayez

private void InitUIState(ViewMode mode) 
{ 
    if (this.InvokeRequired) 
    { 
     this.BeginInvoke((MethodInvoker)delegate 
     { 
      InitUIState(mode); 
     }); 
    } 
    else 
    { 
     this.labelProgramStatus.Text = CONSOLE_IDLE_STATUS; 
    } 
} 
+0

Comme indiqué dans les commentaires, en raison de ma poignée de gagner pas être créé c'est la raison pour laquelle mon fil dans cette instance m'a toujours permis de mettre à jour le fil de l'interface utilisateur directement. Un événement très rare je pense! – GONeale

-1

Invoke et BeginInvoke sur les délégués ne sont pas les mêmes que ISynchronizeInvoke.

Vous devez également appeler le EndInvoke lorsque vous traitez avec un délégué.

+0

Vous n'avez pas besoin de leppie. – GONeale

+0

@GONeale: Vous le faites, si vous ne voulez pas fuir le WaitHandle. Mais je suppose que cela dépend de vous. – leppie

0

Vous mélangez BeginInvoke de Form et Delegate, car les deux ont le même nom de méthode.

La méthode du formulaire BeginInvoke appelle la méthode demandée dans le même thread d'interface utilisateur, mais à un stade ultérieur, après avoir traité ses propres opérations d'interface utilisateur en attente. C'est la raison, InvokeRequired sera toujours false dans la méthode BeginInvoke du formulaire.

La méthode du délégué BeginInvoke appelle la méthode sur un nouveau thread de manière asynchrone dans le pool de threads. Et InvokeRequired dans BeginInvoke du délégué sera toujours vrai.

+0

Désolé cela ne m'a pas aidé. Je ne les mélange pas, this.BeginInvoke() exécutera son contenu sur le thread principal de l'interface utilisateur. delegate.BeginInvoke() exécutera son contenu sur un nouvel élément de travail dans ThreadPool. Cela ne m'explique pas pourquoi InvokeRequired = false. – GONeale

+0

Chaque fois que quelque chose s'exécute sur le thread UI, InvokeRequired sera faux, désolé ne peut pas expliquer mieux que cela. –

+0

+1 pour indiquer l'évidence. – bleevo

Questions connexes