2013-11-15 8 views
2

Я знаю, что этот вопрос задавали 100 раз раньше, но все ответы, которые я прочитал, не сработали для меня. Итак, я попробую удачу и попрошу еще раз.Обновление ProgressBar из другой темы

У меня есть SliderBar, который вызывает метод на событии ValueChanged. В этом методе я делаю некоторые вещи, которые требуют времени, и я хочу, чтобы в это время пользователь увидит «рабочий» ProgressBar (IsIndeterminate=true).

К сожалению, мне не удалось заставить ProgressBar начать работу (в пользовательском интерфейсе) до тех пор, пока все контуры метода не закончатся. Я пробовал темы, BackgroundWorker и async Задачи, но без успеха ..

Что я делаю неправильно?

Это метод:

private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e){ 
     WorkingBar.IsIndeterminate = true;  //change the progressBar   
     SqlAThread = new Thread(SqlAStart);  
     SqlAThread.Start(); 
    } 

Нить:

private void SqlAStart() 
    { 
     ... //do some stuff 
    } 
+0

Синтаксис диспетчера в вашем методе doWork - это то, что вы хотите использовать, вы хотите поместить свой код пользовательского интерфейса, чтобы нажать действия, которые вы хотите сделать, на поток пользовательского интерфейса, на данный момент все, что вы, кажется, делаете здесь, это изменяя свойство индикатора выполнения, используйте этот синтаксис, чтобы обновить индикатор выполнения. – JMK

+0

@JMK это пропартий - это то, что я хочу изменить, когда это свойство является «истинным», прогресс progress достигнут в «рабочем» режиме (я думаю ...?). на самом деле, он работает, но только при выполнении всего цикла. =/ – Yaron

ответ

3

В Slider_ValueChanged вы начинаете новый рисунок протектора для запуска SqlAStart() метод трудоемкий, но SqlAStart сразу толкает работу назад в потоке пользовательского интерфейса (через Dispatcher.Invoke()). Поэтому ваш пользовательский интерфейс зависает, и вы не видите никакого прогресса ProgressBar, пока работа не будет выполнена.

В SqlAStart, только сделать Dispatcher.Invoke(), где вам необходимо обновить индикатор:

private void SqlAStart() 
{ 
    ServerThread = new Thread(HttpSrv.listen); 
    ServerThread.Start(); 
    ... 

    this.Dispatcher.Invoke((Action)(() => { 
     WorkingBar.Value = ...     
    })); 

    .... 
} 
+0

Это тоже должно работать. – Marc

+0

@Sphinxxx Спасибо! – Yaron

0

Вместо того, чтобы впечатать весь длительный процесс, я приглашаю вас взглянуть на мой ответ на Progress Bar update from Background worker stalling вопрос здесь о StackOverflow. Он демонстрирует, как правильно использовать объект BackgroundWorker для обновления значения прогресса ProgressBar.

Вы также можете просмотреть страницу BackgroundWorker Class на MSDN для получения более подробной информации.

+0

Привет @sheridan Я попробовал ваш код (на самом деле это была моя первая попытка) Я понимаю ваш пример, но не смог использовать его в своем коде .. – Yaron

+0

@Yaron, пока игнорируйте свой код. Поместите этот примерный код в новое приложение или проект WPF и получите его работу. * Затем * с рабочим примером для экспериментирования вы должны * * * * * * * * * * * * * * * * * * * * – Sheridan

+0

Я пробовал и работал в новом проекте. но теперь, когда я пытаюсь сделать это в своем коде, он работает для меня – Yaron

1

Это довольно легко с помощью IProgress<T>:

private async void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) 
{ 
    if (State.Value > 0) 
    { 
    var progress = new Progress<int?>(value => 
    { 
     WorkingBar.IsIndeterminate = (value == null); 
     if (value != null) 
     WorkingBar.Value = value.Value; 
    }); 
    await Task.Run(() => doWork(progress)); 
    Task.Run(SqlAStart); 
    } 
    ... 
} 

private void SqlAStart(IProgress<int?> progress) 
{ 
    ServerTask = Task.Run(HttpSrv.listen); 
    ... 
} 

private void doWork(IProgress<int?> progress) 
{ 
    if (progress != null) 
    progress.Report(null); 
    ... 
} 

Обратите внимание, что вы должны (почти) не использовать Dispatcher, Thread, или BackgroundWorker в современных приложениях.

+0

Hi @Stephen Cleary, я попробовал ваш код (btw, спасибо, я дознал, что знал IProgress ), но все же обновление UI сразу после завершения SqlAstart. – Yaron

+0

@Yaron Что делает этот метод? Если он вызывает поток пользовательского интерфейса и блокирует его некоторое время, то, очевидно, ничто еще не может обновить его, пока оно выполняется. – Servy

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