2009-02-19 3 views
1

J'ai un formulaire Windows avec une étiquette et une zone d'image. Pour récupérer une image d'un service Web, j'utilise un thread.C# Threads et mise à jour de l'affichage

L'utilisateur clique sur un bouton et d'abord l'étiquette doit être affichée, puis un nouveau fil est démarré pour récupérer l'image. C'est le code:

private void menuItem1_Click(object sender, EventArgs e) 

{ 

etiquetaCargando.Visible = true; 

this.Invoke(new System.Threading.ThreadStart(RequestImage)); 

} 

Le problème est le suivant: étiquette etiquetaCargando n'apparaît pas.

Je programme sur Compact Framework.

Qu'est-ce qu'il se passe?

Merci!

+0

On ne sait pas quelle est la question. Y a-t-il un problème que vous essayez de résoudre ou demandez-vous comment démarrer un thread? –

+0

L'étiquette etiquetaCargando n'apparaît pas. – VansFannel

Répondre

3

La question n'est pas claire, mais en utilisant Invoke, vous désactivez le but d'avoir la demande d'image sur un thread séparé. (Vous remarquerez peut-être que votre interface ne répond plus pendant que la requête est en cours)

Au lieu de cela, il est préférable de créer un objet thread, de le démarrer, puis d'utiliser l'Invoke pour définir l'image (après qu'elle a été récupérée) , quelque chose le long des lignes de

private void menuItem1_Click(object sender, EventArgs e) 
{  
    etiquetaCargando.Visible = true; 
    Thread reqThread = 
     new Thread(new ThreadStart(RequestImage)); 
    reqThread.Start(); 
} 

private void RequestImage() 
{ 
    /* Get the image 
    ... 
    */ 
    Invoke(SetTheImage, new object[] { theImage }); 
} 

cela suppose que vous avez une SetTheImage méthode qui fait faire le travail d'afficher l'image sur votre formulaire.

+0

Dans la méthode RequestImage je dois accéder à ces propriétés: this.Hauteur this.Width Comment puis-je récupérer les valeurs de ces deux propriétés? – VansFannel

+0

@VansFannel: Vous devriez pouvoir y accéder directement, sinon vous pouvez passer la taille dans un ThreadStart paramétré, et demander à RequestImage de prendre la taille comme paramètre –

3

Vous ne devriez pas appellerez ceci:

this.Invoke(new System.Threading.ThreadStart(RequestImage)); 

Je suppose que vous supercondamnation ici, comme méthode Invoke acheminera le délégué au fil de l'interface utilisateur, mais vous attendez de votre opération pour terminer.

Pour obtenir le code à exécuter sur un autre thread, vous feriez ceci:

private void menuItem1_Click(object sender, EventArgs e) 
{ 
    etiquetaCargando.Visible = true; 

    Thread t = new Thread(RequestImage); 

    t.Start(); 
} 

Ensuite, dans votre méthode de RequestImage, vous appelez la méthode Invoke, le passage d'un délégué à exécuter sur le thread d'interface utilisateur , dans ce cas, en passant l'image que vous avez téléchargé.

+0

N'oubliez pas de Commencer ce nouveau t. ;) – JMD

+0

@JMD: Code ajouté basé sur un commentaire. – casperOne

+0

Si je fais cela, l'étiquette devient visible mais je ne peux pas représenter l'image récupérée du service Web. – VansFannel

0

Vous pouvez effectuer les opérations suivantes:

private void menuItem1_Click(object sender, EventArgs e) 
{ 
    etiquetaCargando.Visible = true; 
    Thread t = new Thread(new ThreadStart(RequestImage)); 

    // NOTE THIS LINE 
    // Without this, if your application is closed and the thread isn't, 
    // it will leave your program in memory until it does 
    t.IsBackground = true; 

    this.Invoke(new System.Threading.ThreadStart(RequestImage)); 
} 

private void RequestImage() 
{ 
    // Do the work here 
    // let's assume img is the image you've got 

    // Prepare a delegate to invoke 
    MethodInvoker m = (MethodInvoker)delegate() { 
     myImage.Image = img; 
    }; 

    // Invoke it on the UI thread if needed, otherwise 
    // do a straight invoke 
    if (this.InvokeRequired) 
     this.Invoke(m); 
    else 
     m.Invoke(); 
} 
+0

Peut-être que this.IsBackground n'est pas nécessaire. Inside RequestImage J'ai besoin d'accéder à deux propriétés: this.Height et this.Width. Comment puis-je faire ceci? – VansFannel

+0

Vous pouvez accéder à ceux qui utilisent 'System.Drawing.Size' IIRC, en déclarant votre propre méthode delegate (' delegate Size getSizeDelegate (Control c); 'ailleurs dans le code), en remplaçant' MethodInvoker' par 'getSizeDelegate', en ajoutant' Contrôlez c' à 'delegate()' et renvoyez la taille depuis l'intérieur de son corps. :) –

0

Comme d'autres l'ont dit, vous utilisez l'Invoke en arrière.

Ma suggestion est quelque chose comme ceci dans votre gestionnaire d'origine:

ThreadPool.QueueUserWorkItem(RequestImage) 

puis utilisez un lambda pour faire le invoquerez RequestImage:

RequestImage() 
{ 
    ... 
    ... 

    Invoke(() => { myControl.BackgroundImage = img; myControl.Width = img; etc, etc }); 
} 

Ou quelque chose comme ça.

Questions connexes