2 votes

Modèle pour gérer l'état des threads en C#

Je suis en train de développer un programme qui doit gérer plusieurs threads. Lorsque je démarre le programme, je lance plusieurs threads (mon exemple est limité à un seul). Je dois afficher leur état dans une seule TextBox. J'ai opté pour la solution suivante. Cette solution est-elle correcte ? Existe-t-il d'autres modèles ? L'observateur peut-être ? Je n'arrive pas à trouver une bonne façon de faire cela sur le web.

namespace ThreadTest
{
    public partial class Form1 : Form
    {
        // This delegate enables asynchronous calls for setting
        // the text property on a TextBox control.
        delegate void ChangedCallback(object sender, JobEventArgs e);

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            MyThread myThread = new MyThread();
            myThread.Changed += new MyThread.JobEventHandler(myThread_Changed);

            // Create the thread object, passing in the Alpha.Beta method
            // via a ThreadStart delegate. This does not start the thread.
            Thread oThread = new Thread(new ThreadStart(myThread.MyJob));

            // Start the thread
            oThread.Start();
        }

        void myThread_Changed(object sender, JobEventArgs e)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.textBox1.InvokeRequired)
            {
                ChangedCallback d = new ChangedCallback(myThread_Changed);
                this.Invoke(d, new object[] { sender, e });
            }
            else
            {
                // Display the status of my thread
                textBox1.Text += e.Counter;
            }
        }
    }

    public class MyThread
    {
        // A delegate type for hooking up change notifications.
        public delegate void JobEventHandler(object sender, JobEventArgs e);

        // An event that clients can use to be notified whenever the
        // elements of the list change.
        public event JobEventHandler Changed;

        // Invoke the Changed event; called whenever list changes
        protected virtual void OnChanged(JobEventArgs e)
        {
            if (Changed != null)
                Changed(this, e);
        }

        public void MyJob()
        {
            for (int i = 0; i < 1000; i++)
            {
                Thread.Sleep(1000);
                JobEventArgs e = new JobEventArgs(i);
                OnChanged(e);
            }
        }
    }

    public class JobEventArgs
    {

        public int Counter { get; set; }

        public JobEventArgs(int i)
        {
            Counter = i;
        }
    }
}

3voto

vidstige Points 4541

Ça m'a l'air très bien. En fait, vous sont en utilisant le modèle de l'observateur. C'est juste la belle syntaxe événementielle de C# qui élimine l'interface et réduit la paperasse.

Cependant, il y a beaucoup de code redondant et d'autres problèmes de lisibilité.

  • Le site this est redondant lorsqu'il s'agit de spécifier un membre tel que this.textBox1 ou this.Invoke(...) .
  • Essayez de toujours spécifier une visibilité telle que private ou public pour les méthodes.
  • Un délégué approprié est créé automatiquement autour d'un groupe de méthodes, ce qui permet une syntaxe raccourcie. Par exemple : new Thread(myThread.MyJob) ou myThread.Changed += myThread_Changed .
  • Envisagez d'utiliser de simples actions comme types de délégués de traitement d'événements au lieu d'un système personnalisé ( ChangedCallback ). La méthode myThread_Changed peut alors n'accepter qu'un int comme paramètre unique, ce qui vous permet de supprimer de nombreux types redondants.
  • Pour éviter les problèmes, faites une copie locale de l'événement avant de vérifier s'il est nul et de l'invoquer.

Comme ça :

JobEventHandler tmp = Changed;
if (tmp != null) tmp(this, e);

3voto

jgauffin Points 51913

Votre code n'est pas bon.

  1. Pourquoi ne laissez-vous pas votre classe de fil créer le fil ? C'est plus logique et cela donne une belle encapsulation :
  2. Vous ne devriez pas déclarer les délégués à l'intérieur d'une classe, cela rend le remaniement plus difficile.
  3. Si vous dormez dans le fil, pourquoi ne pas utiliser une Timer à la place ?

#

public partial class Form1
{
    delegate void ChangedCallback(object sender, JobEventArgs e);

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        MyThread myThread = new MyThread();
        myThread.Changed += myThread_Changed;
        myThread.Start();
    }

    void myThread_Changed(object sender, JobEventArgs e)
    {
        if (this.textBox1.InvokeRequired)
        {
            ChangedCallback d = new ChangedCallback(myThread_Changed);
            this.Invoke(d, new object[] { sender, e });
        }
        else
        {
            textBox1.Text += e.Counter;
        }
    }
}

public class MyThread
{
    private Thread _thread;

    public MyThread()
    {
        _thread = new Thread(WorkerFunc);
    }

    public void Start()
    {
        _thread.Start();
    }

    // use the = {} pattern since you are using multithreading.
    public event JobEventHandler Changed = {};

    protected virtual void OnChanged(JobEventArgs e)
    {
        Changed(this, e);
    }

    private void WorkerFunc()
    {
        for (int i = 0; i < 1000; i++)
        {
            Thread.Sleep(1000);
            JobEventArgs e = new JobEventArgs(i);
            OnChanged(e);
        }
}

// A delegate type for hooking up change notifications.
public delegate void JobEventHandler(object sender, JobEventArgs e);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X