Обновить метку при обработке в Windows Forms - PullRequest
31 голосов
/ 20 февраля 2009

Каков наилучший способ обновления метки в приложении Windows Forms во время обработки?

У меня есть цикл, который выполняет некоторую обработку файлов в системе пользователя, когда пользователь нажимает кнопку.

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..."
}

Какой будет пример кода?

Что именно это называется? Это многопоточность или делегаты?

Ответы [ 5 ]

58 голосов
/ 20 февраля 2009

Быстрое решение для вас будет:

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

Вы действительно хотите избежать DoEvents, иначе у вас будут проблемы, если ваш пользователь неоднократно нажимает кнопки в вашей форме.

13 голосов
/ 21 февраля 2009

Вам нужно будет перенести данные из одного потока в другой. Это можно сделать несколькими способами ...

Во-первых, ваш "фоновый" поток может обновить какую-то строковую переменную "CurrentStatus", которая изменяется по мере продвижения. Затем вы могли бы добавить в форму таймер, который затем захватил бы переменную CurrentStatus и обновил бы метку.

Во-вторых, вы можете просто вызвать операцию из фонового потока в поток пользовательского интерфейса с делегатом, используя свойство InvokeRequired элемента управления меткой. Так например ...

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;
}

Вы можете вызвать этот метод UpdateStatus () из любого потока (пользовательского интерфейса или фона), и он определит, нужно ли ему вызывать операцию в основном потоке пользовательского интерфейса (и если да, то делает ли это).

Чтобы на самом деле настроить поток, вы можете сделать это так:

    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 + "...");                
        }
    }

Затем, когда пользователь нажимает кнопку «GO», вы просто вызываете StartProcessing ().

13 голосов
/ 20 февраля 2009

Вы должны сделать это в другом потоке, а затем обновить ваш поток пользовательского интерфейса из этого потока. Вы блокируете дальнейшую обработку, выполняя эту работу в потоке пользовательского интерфейса.

Если вы не можете переместить этот код в поток пользовательского интерфейса, то вы всегда можете вызвать Application.DoEvents, но я настоятельно предлагаю вам изучить Варианты сначала:

1 голос
/ 20 февраля 2009

Если ваша обработка занимает много времени, сделайте это в потоке фонового рабочего.

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

0 голосов
/ 14 марта 2019

Я также рекомендую использовать:

Application.DoEvents();

Обрабатывает все сообщения Windows, находящиеся в данный момент в очереди сообщений.

...