Есть ли какая-нибудь команда для немедленного обновления пользовательского интерфейса?

Я хочу обновить индикатор выполнения с 1 до 100 с помощью этого кода.

for (int i = 0; i <= 100; i++) {
    System.Threading.Thread.Sleep(100);
    progressBar1.Value = i;
}

Но в результате пользовательский интерфейс зависает до завершения цикла.

Я знаю, что Dispatcher может помочь, но я не хочу разделять функции.

Есть ли какая-нибудь команда для немедленного обновления пользовательского интерфейса, например...

for (int i = 0; i <= 100; i++) {
    System.Threading.Thread.Sleep(100);
    progressBar1.Value = i;
    UpdateUINow();
}

Изменить: я использую WPF и использую Thread.Sleep для имитации длительного процесса.

На самом деле, я хочу, чтобы любая команда понравилась Application.DoEvents. Но я не могу найти эту команду в WPF.


person Chaowlert Chaisrichalermpol    schedule 19.11.2009    source источник


Ответы (5)


Пожалуйста, не засыпайте в потоке пользовательского интерфейса. Это заморозит ваш пользовательский интерфейс — это плохо.

Либо используйте какой-либо таймер (используйте правильный тип таймера, и вы сможете запустить его в потоке пользовательского интерфейса), либо используйте отдельный поток (либо через BackgroundWorker, либо через новый отдельный поток, либо через ThreadPool) и сделайте он обращается к потоку пользовательского интерфейса, чтобы обновить его.

Application.DoEvents - это хакерский обходной путь в WinForms, но тот факт, что вы упомянули Dispatcher, предполагает, что вы используете WPF - так ли это? Тип таймера, который вы должны использовать (если вы хотите использовать это решение), будет зависеть от используемой вами инфраструктуры пользовательского интерфейса.

person Jon Skeet    schedule 19.11.2009
comment
Invoke(delegateInstance) выполнит эту работу в WinForms. - person mmx; 19.11.2009
comment
+1 Так рад, что кто-то смог противостоять постоянно растущему списку DoEvents рекомендаций, пока я ел свои куриные палочки. - person Adam Robinson; 19.11.2009

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

person Stephen Wrighton    schedule 19.11.2009

Я бы использовал C# BackgroundWorker для обновления пользовательского интерфейса. Это не работает так, как вы ожидаете, потому что Thread.Sleep() замораживает ваш поток пользовательского интерфейса.

РЕДАКТИРОВАТЬ: Учебник, который делает немного больше, чем вы хотите здесь

person Scott Anderson    schedule 19.11.2009

То же самое с ожиданием в основном потоке (GUI) - избегайте этого любой ценой. Хотя вы не хотите использовать Dispatcher, я все же рекомендую попробовать (что-то вроде) это:

public partial class Window1 : Window
{
    DispatcherTimer _timer = new DispatcherTimer();

    public Window1()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        progressBar1.Value = 0;
        progressBar1.Maximum = 100;
        _timer.Interval = TimeSpan.FromMilliseconds( 100);
        _timer.Tick += ProgressUpdateThread;
        _timer.Start();
    }

    private void ProgressUpdateThread( object sender, EventArgs e)
    {
        progressBar1.Value++;
    }
}
person Dave    schedule 20.11.2009

Узнайте, может ли DoEvents помочь вам. прочь.

person luvieere    schedule 19.11.2009