Показывать busyindicator в приложении wpf - PullRequest
1 голос
/ 01 сентября 2011

У меня есть BusyIndicator из расширенного инструментария wpf, и я запускаю функцию, выполнение которой занимает некоторое время. Если я запускаю трудоемкую задачу в отдельном потоке, я получаю NotSupportedException, потому что я пытаюсь вставить объекты в ObservableCollection из этого другого потока. Я не хочу тратить много времени на рефакторинг кода, если это возможно ... Можно ли вместо этого установить видимость индикатора в отдельном потоке?

EDIT

ThreadStart start = delegate()
  {
      System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
          {
              IsBusy = true;
          }));
   };

new Thread(start).Start();                                
longRunningFunction();

У меня это тоже не сработало.

Ответы [ 2 ]

1 голос
/ 01 сентября 2011

Вы должны быть в состоянии использовать Dispatcher для подобных вещей.например,

Application.Current.Dispatcher.Invoke((Action)(() =>
{
    _indicator.Visibility = Visibility.Visible;
}));

Это приведет к запуску кода в потоке пользовательского интерфейса.

Более подробная информация (в том числе о том, как "правильно" сделать это с помощью CheckAccess и т. П.) На нем в справочнике по модели потоков .

0 голосов
/ 01 сентября 2011

Вы не можете получить доступ к элементам управления пользовательского интерфейса из фонового работника.Обычно вы устанавливаете IsBusy в значение true, прежде чем вызывать BackgroundWorker.RunWorkerAync (), затем в обработчике события BackgroundWorker.RunWorkerCompleted вы устанавливаете IsBusy в значение false.Примерно так:

Backgroundworker worker = new BackgroundWorker();
worker.DoWork += ...
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
     IsBusy = false;
};
IsBusy = true;
worker.RunWorkerAsync();

Вы можете использовать Диспетчер для добавления элементов в ObservableCollection, находясь в обработчике событий DoWork.

РЕДАКТИРОВАТЬ : Вот полное решение

        private void Button_Click(object sender, RoutedEventArgs e)
    {
        //on UI thread
        ObservableCollection<string> collection;

        ThreadStart start = delegate()
        {
            List<string> items = new List<string>();
            for (int i = 0; i < 5000000; i++)
            {
                items.Add(String.Format("Item {0}", i));
            }

            System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
            {
                //propogate items to UI
                collection = new ObservableCollection<string>(items);
                //hide indicator
                _indicator.IsBusy = false;
            }));
        };
        //show indicator before calling start
        _indicator.IsBusy = true;
        new Thread(start).Start();      
    }
...