Aktualizuj Etykietę podczas przetwarzania w formularzach Windows

Jaki jest najlepszy sposób aktualizacji etykiety w aplikacji Windows Forms podczas przetwarzania?

Mam pętlę, która przetwarza pliki w systemie użytkownika, gdy użytkownik kliknie przycisk.

foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
{
   // Do processing
   // Show progress bar
   // Update Label on Form, "f.Name is done processing, now processing..."
}

Jaki byłby przykładowy kod?

Jak to się właściwie nazywa? Gwintowanie czy delegowanie?
Author: default locale, 2009-02-20

4 answers

Szybkie rozwiązanie dla ciebie to:

Label1.Text = f.Name + " is done processing, now processing...";
Label1.Refresh();

Naprawdę chcesz uniknąć DoEvents, w przeciwnym razie będziesz miał problemy, jeśli użytkownik wielokrotnie naciska przyciski w formularzu.

 50
Author: Patrick McDonald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-30 03:27:36

Ty powinieneś robić to w innym wątku, a następnie aktualizować swój wątek UI z tego wątku. Blokujesz dalsze przetwarzanie, wykonując tę pracę w wątku UI.

Jeśli nie możesz przenieść tego kodu do wątku UI, zawsze możesz wywołać Application.DoEvents, Ale ja zdecydowanie sugeruję najpierw zbadanie tych opcji:

 13
Author: casperOne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-30 03:27:26

Musisz przenieść swoje dane z jednego wątku do drugiego. Można to zrobić na kilka sposobów...

Po pierwsze, Twój wątek "background" może zaktualizować jakąś zmienną łańcuchową "CurrentStatus", którą zmienia w miarę upływu czasu. Następnie możesz umieścić timer na formularzu, który następnie pobierze zmienną CurrentStatus i zaktualizuje Etykietę.

Po drugie, możesz po prostu wywołać operację z wątku tła do wątku interfejsu użytkownika za pomocą delegata przy użyciu InvokeRequired property of the label control. Na przykład...

private delegate void UpdateStatusDelegate(string status);
private void UpdateStatus(string status)
{
    if (this.label1.InvokeRequired)
    {
        this.Invoke(new UpdateStatusDelegate(this.UpdateStatus), new object[] { status });
        return;
    }

    this.label1.Text = status;
}

Możesz wywołać tę metodę UpdateStatus() z dowolnego wątku (UI lub tła), a ona wykryje, czy musi wywołać operację na głównym wątku UI (a jeśli tak, to zrobi to).

Aby skonfigurować wątek, możesz zrobić tak:

    private void StartProcessing()
    {
        System.Threading.Thread procThread = new System.Threading.Thread(this.Process);

        procThread.Start();
    }

    private void Process() // This is the actual method of the thread
    {
        foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
        {
            // Do processing
            // Show progress bar
            // Update Label on Form, "f.Name is done processing, now processing..."
            UpdateStatus("Processing " + f.Name + "...");                
        }
    }

Następnie, gdy użytkownik kliknie przycisk "GO", wywołasz po prostu metodę StartProcessing ().

 13
Author: Brandon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-24 15:25:06

Jeśli przetwarzanie jest długie, zrób to w wątku backgroundworker.

Http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

 1
Author: devSpeed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-20 17:37:31