2009-12-17 9 views
2

У меня есть форма Windows со строкой состояния, которая показывает текущее состояние приложения. У меня есть класс с именем AppState с обновлением Label в строке состояния и в распоряжении он меняет состояние на «Готово».Текст ярлыка не обновлен

В коде, когда я делаю операцию, как:

using (AppState state = new AppState("Processing...")) 
{ 
    //Do some work that take some seconds 
} 

Но метка осталась прежней. У меня нет никаких исключений. Текст метки обновляется, но в пользовательском интерфейсе он продолжает показывать предыдущее значение. Я что-то пропустил?

santosc Вы правы, это единственное, что я делаю. Вот код AppState

public class AppState : IDisposable 
{ 
    static string Default = "Ready"; 

    public AppState(string status) 
    { 
     Form.StatusLabel.Text = status; 
    } 

    public void Dispose() 
    { 
     Form.StatusLabel.Text = Default; 
    } 
} 
+0

Опубликовать код, который фактически изменяет метку ... –

+0

Можете ли вы показать, что делает код AppState? Я подозреваю, что вы устанавливаете новый текст статуса, но не даете окнам возможность перерисовать его. – santosc

ответ

5

Это всегда то же самое ...

Если вы хотите, чтобы начать то, что занимает некоторое время, не делайте этого в вашем GUI потока или графический интерфейс не замерзнет (нет обновлений этикетки, не изменения размера, не двигаясь, ничем).

Заполнение вашего кода на тысячу мест с помощью приложения.DoEvents() также является плохой практикой.

Если у вас есть задание на длительное время (длинные средства> 1 с), вы, вероятно, должны использовать BackgroundWorker. Может быть, это немного сложнее в начале, но вам понравится, если ваша программа станет более сложной. В связи с тем, что это уже обсуждалось несколько раз, вот link with some sample code.

Теперь, когда вы знаете правильный инструмент (BackgroundWorker), чтобы решить вашу проблему, вы должны заставить его работать (или задать другой вопрос о вашей новой конкретной проблеме).

+0

... но serhio и mrduclaw (такой же) также работает. – ata

+0

@ cornerback84: Во-первых, всегда может быть только один ответ отмечен как правильный. Во-вторых, возможно, двое других дали хорошее направление, но я думаю, что мои две ссылки предоставят вам хорошую карту о том, как делать подобные вещи. И последнее, но не менее важное: это тот, кто задает вопрос, чтобы судить о том, что он считает правильным *, любой другой может просто возвысить все, что захочет. – Oliver

4

Похоже, вы хотите поставить Application.DoEvents() после установки значения StatusLabel текстового поля. Это говорит Windows Forms обрабатывать очередь событий Windows для вашей формы, в результате чего изменения должны быть перекрашены.

+1

Это очень плохое обходное решение. – Matthias

+2

@ winSharp93 - Я думаю, это зависит от вашего приложения. Создание новой темы в BackgroundWorker требует, чтобы класс, который вы вызываете, был потокобезопасным и был более сложным, чем добавление одного вызова метода. Также может потребоваться разработка приложения для предотвращения выбора некоторых опций в зависимости от того, чем занимается BackgroundWorker. Не тривиально. –

+0

Я не согласен - Application.DoEvents только заботится о последствиях, а не о причинах. – Matthias

0

Возможно, несколько потоков могут решить вашу проблему.

Самый простой способ - использовать BackgroundWorker.

Причина в том, что пользовательский интерфейс может только перерисовывать, когда нить пользовательского интерфейса не имеет ничего другого. И вы блокируете его своими расчетами.

+0

Будет ли Control.BeginInvoke решить проблему? – ata

+0

Это понадобится вам при использовании нескольких потоков, поэтому это часть решения. Однако без потоков это ничего не меняет. – Matthias

2

для того, чтобы быть «поточно» использовать Invoke и тест с InvokeRequired в форме, как:

// code outside the myForm:----------------------- 
    if (myForm.InvokeRequired) 
     myForm.Invoke(new ChangeLabelEventHandler(ChangeLabel), "teeeest"); 
    else 
     myForm.ChangeLabel("teeeest"); 


    // code in the myForm:----------------------------- 
    public delegate void ChangeLabelEventHandler(string newText); 

    private void ChangeLabel(string newLabelText) 
    { 
     this.label1.Text = newLabelText; 
    } 
+0

Да, это должно работать нормально. Но - безопасность потока находится только между новым потоком BackgroundWorker и потоком пользовательского интерфейса. Это не останавливает пользователя, нажимая кнопку «идти» (или выбор меню или whathaveyou), чтобы одновременно запускать/другой/BackgroundWorker. Это может иметь неожиданные последствия. –

+0

Чтобы предотвратить это, вы можете просто проверить BackgroundWorker.IsBusy, чтобы увидеть, есть ли текущая работа. – Oliver

+0

В моем примере, я считаю, есть ** любая потребность в backgroundWorker **. – serhio

2

Я новичок в C# вещи, но почему вы не можете просто сделайте что-нибудь вроде:

private void updateStatusBar(string status) 
{ 
    if (StatusLabel.InvokeRequired) 
    { 
     StatusLabel.Invoke((MethodInvoker)(() => 
        { 
         StatusLabel.Text = status; 
        })); 
    } 
    else 
    { 
     StatusLabel.Text = status; 
    } 
} 

Если вы хотите обновить статус?

+0

просто проверьте ранее, если StatusLabel.InvokeRequired, чтобы немного оптимизировать. – serhio

+0

Спасибо! Как это? :) – mrduclaw

+0

........ о да! – serhio

0

использование Label.Refresh(); это экономит много времени. Это должно работать для u

Смежные вопросы