2010-10-18 3 views
7

Dans mon application j'utilise une minuterie pour vérifier les mises à jour dans un flux RSS, si de nouveaux éléments sont trouvés, j'ouvre une boîte de dialogue personnalisée pour informer l'utilisateur. Lorsque je lance la vérification manuellement, tout fonctionne très bien, mais lorsque la vérification automatique s'exécute dans l'événement Elapsed timers, la boîte de dialogue personnalisée n'est pas affichée.Méthode d'appel sur le thread GUI à partir d'un thread timers

Tout d'abord est-ce un problème de thread? (Je suppose que c'est parce que le contrôle manuel et automatique utilisent le même code).

Lorsque j'exécute la vérification automatique, dois-je appeler la méthode qui exécute la vérification à partir du gestionnaire d'événements Temporis Elapsed?

Y a-t-il quelque chose que je dois faire dans ma classe de dialogue personnalisé?

Édition: Ceci est une application winforms.

Voici un exemple de ce qu'est le code. (S'il vous plaît ne pas signaler les erreurs de syntaxe dans cet exemple de code, ce n'est qu'un exemple simple, pas de code réel).

public class MainForm : System.Windows.Forms.Form 
{ 
    //This is the object that does most of the work. 
    ObjectThatDoesWork MyObjectThatDoesWork = new ObjectThatDoesWork(); 
    MyObjectThatDoesWork.NewItemsFound += new NewItemsFoundEventHandler(Found_New_Items); 

    private void Found_New_Items(object sender, System.EventArgs e) 
    { 
     //Display custom dialog to alert user. 
    } 

    //Method that doesn't really exist in my class, 
    // but shows that the main form can call Update for a manual check. 
    private void Button_Click(object sender, System.EventArgs e) 
    { 
     MyObjectThatDoesWork.Update(); 
    } 

    //The rest of MainForm with boring main form stuff 
} 


public class ObjectThatDoesWork 
{ 
    System.Timers.Timer timer; 

    public ObjectThatDoesWork() 
    { 
     timer = new System.Timers.Timer(); 
     timer.Interval = 600000; 
     timer.AutoReset = true; 
     timer.Elapsed += new new System.Timers.ElapsedEventHandler(TimeToWork); 
     timer.Start(); 
    } 

    private void TimeToWork(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     Update(); 
    } 

    public void Update() 
    { 
     //Check for updates and raise an event if new items are found. 
     //The event is consumed by the main form. 
     OnNewItemsFound(this); 
    } 

    public delgate void NewItemsFoundEventHandler(object sender, System.EventArgs e); 
    public event NewItemsFoundEventHandler NewItemsFound; 
    protected void OnNewItemsFound(object sender) 
    { 
     if(NewItemsFound != null) 
     { 
      NewItemsFound(sender, new System.EventArgs()); 
     } 
    } 
} 

Après avoir lu certains des commentaires et des réponses, je pense que mon problème est que je me sers d'un System.Timers.Timer pas System.Windows.Forms.Timer.

EDIT:

Après le passage à un test initial Forms.Timer semble bon (mais pas de nouveaux éléments encore existent pour n'ont pas vu la boîte de dialogue personnalisée). J'ai ajouté un peu de code pour afficher l'ID de thread dans un fichier lorsque la méthode de mise à jour est appelée. À l'aide de Timers.Timer, l'ID de thread n'était pas le thread graphique, mais en utilisant le Forms.Timer l'ID de thread est identique à l'interface graphique.

+3

Oui, c'est un problème de threading - mais la réponse dépend de si vous utilisez WPF ou WinForms: c'est quoi? – x0n

+0

Et je suis surpris que vous ne voyez aucune exception: quelle version de .NET utilisez-vous? Pouvez-vous montrer un exemple de code? –

+0

Pouvez-vous s'il vous plaît poster le code? – TalentTuner

Répondre

15

Which timer l'utilisez-vous? System.Windows.Forms.Timer déclenche automatiquement l'événement sur le thread UI. Si vous en utilisez un autre, vous devrez utiliser Control.Invoke pour appeler la méthode sur le thread UI.

+0

La modification en System.Windows.Forms.Timer a résolu le problème. Je vous remercie. – Tester101

+0

+1000! System.Windows.Forms.Timer résout tous mes problèmes de minuterie "Objet créé sur un autre thread" très frustrant! Merci! –

+0

comme une blague, j'ai passé une journée pour ça! Merci et soyez conscient – aozan88

1

Vous devez utiliser Forms.Timer ici, ou si vous utilisez un autre type de minuteries, sérialisation appels à l'interface utilisateur avec .Invoke()

0
private static System.Threading.SynchronizationContext _UI_Context; 
    //call this function once from the UI thread 
    internal static void init_CallOnUIThread() 
    { 
     _UI_Context = System.Threading.SynchronizationContext.Current; 
    } 
    public static void CallOnUIThread(Action action, bool asynchronous = false) 
    { 
     if (!asynchronous) 
      _UI_Context.Send((o) => 
      { 
       action(); 
      }, null); 
     else 
      _UI_Context.Post((o) => 
      { 
       action(); 
      }, null); 
    } 
Questions connexes