1592 Stimmen

Wie aktualisiere ich die GUI von einem anderen Thread aus?

Welches ist der einfachste Weg, eine Label von einem anderen Thread ?

  • Tengo un Form weiterlaufend thread1 und davon ausgehend eröffne ich ein weiteres Thema ( thread2 ).

  • Während thread2 einige Dateien verarbeitet, würde ich gerne eine Label sur le Form mit dem aktuellen Status von thread2 Arbeit.

Wie könnte ich das tun?

28 Stimmen

Hat .net 2.0+ nicht die BackgroundWorker-Klasse genau für diesen Zweck. Es UI Thread bewusst. 1. Erstellen Sie einen BackgroundWorker 2. Fügen Sie zwei Delegierte hinzu (einen für die Verarbeitung und einen für den Abschluss)

15 Stimmen

4 Stimmen

Siehe die Antwort für .NET 4.5 und C# 5.0: stackoverflow.com/a/18033198/2042090

5voto

Musculaa Punkte 904

Holen Sie sich zunächst die Instanz Ihres Formulars (in diesem Fall mainForm), und verwenden Sie dann einfach diesen Code in einem anderen Thread.

mainForm.Invoke(new MethodInvoker(delegate () 
{
    // Update things in my mainForm here
    mainForm.UpdateView();
}));

4voto

Saurabh Punkte 1319

Legen Sie eine gemeinsame Variable in einer separaten Klasse an, um den Wert zu speichern.

Beispiel:

public  class data_holder_for_controls
{
    // It will hold the value for your label
    public string status = string.Empty;
}

class Demo
{
    public static  data_holder_for_controls d1 = new data_holder_for_controls();

    static void Main(string[] args)
    {
        ThreadStart ts = new ThreadStart(perform_logic);
        Thread t1 = new Thread(ts);
        t1.Start();
        t1.Join();
        //your_label.Text=d1.status; --- can access it from any thread
    }

    public static void perform_logic()
    {
        // Put some code here in this function
        for (int i = 0; i < 10; i++)
        {
            // Statements here
        }
        // Set the result in the status variable
        d1.status = "Task done";
    }
}

3voto

Alex Punkte 3047

Der allgemeine Ansatz ist wie folgt:

using System;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        int clickCount = 0;

        public Form1()
        {
            InitializeComponent();
            label1.SetText("0");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            new Thread(() => label1.SetText((++clickCount).ToString())).Start();
        }
    }

    public static class ControlExtensions
    {
        public static void SetText(this Control control, string text)
        {
            if (control.InvokeRequired)
                control.Invoke(setText, control, text);
            else
                control.Text = text;
        }

        private static readonly Action<Control, string> setText =
            (control, text) => control.Text = text;
    }
}

Erläuterung :

Die Antwort lautet in etwa so este . Aber es verwendet eine sauberere (wie für mich) und neuere Syntax. Der Punkt ist InvokeRequired Eigenschaft von control . Es erhält einen Wert, der angibt, ob der Aufrufer eine Invoke-Methode aufrufen muss, wenn er Methodenaufrufe an das Steuerelement vornimmt, weil der Aufrufer sich in einem anderen Thread befindet als der, in dem das Steuerelement erstellt wurde. Wenn wir also aufrufen control.SetText("some text") in demselben Thread control erstellt wurde, ist es in Ordnung, einfach die Text wie diese control.Text = text . Aber bei jedem anderen Thema verursacht es System.InvalidOperationException also muss man eine Methode über control.Invoke(...) zum Einstellen Text zum Thema control wurde erstellt am.

3voto

Ich bevorzuge diese:

private void UpdateNowProcessing(string nowProcessing)
{
    if (this.InvokeRequired)
    {
        Action<string> d = UpdateNowProcessing;
        Invoke(d, nowProcessing);
    }
    else
    {
        this.progressDialog.Next(nowProcessing);
    }            
}

2voto

ipe Punkte 145

In meinem Fall (WPF) ist die Lösung einfach wie folgt:

private void updateUI()
{
    if (!Dispatcher.CheckAccess())
    {
        Dispatcher.BeginInvoke(updateUI);
        return;
    }

    // Update any number of controls here
}

0 Stimmen

Die Frage ist für Winforms.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X