Display busyindicator in wpf application

帅比萌擦擦* 提交于 2019-12-11 07:43:00

问题


I have a BusyIndicator from the wpf extended toolkit and I'm running a function that takes a while to complete. If I run the time consuming task in a separate thread, I get a NotSupportedException because I'm attemping to insert objects into an ObservableCollection from that different thread. I don't really want to spend a lot of time refactoring the code, if possible... Is there a way that I can set the visibility of the indicator in a separate thread instead?

EDIT

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

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

This did not work for me either.


回答1:


You should be able to use the Dispatcher for things like that. e.g.

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

This will cause the code to be run on the UI-Thread.

There is more info (including how to "properly" do this, with CheckAccess and such) on it in the threading model reference.




回答2:


You cannot access UI controls from a background worker. What you normally do is set the IsBusy to true before you call BackgroundWorker.RunWorkerAync(), then in the BackgroundWorker.RunWorkerCompleted event handler you would set the IsBusy to false. Seomthing like:

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

You can use the Dispatcher to add items to your ObservableCollection while in the DoWork event hanlder.

EDIT: Here is the complete solution

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


来源:https://stackoverflow.com/questions/7263227/display-busyindicator-in-wpf-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!