我有一个来自wpf扩展工具包的BusyIndicator,我正在运行一个需要一段时间才能完成的函数。如果我在一个单独的线程中运行耗时的任务,我会得到一个NotSupportedException,因为我正在尝试将对象插入来自该不同线程的ObservableCollection中。我真的不想花很多时间重构代码,如果可能的话......有没有办法可以在单独的线程中设置指标的可见性呢?
修改
ThreadStart start = delegate()
{
System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
{
IsBusy = true;
}));
};
new Thread(start).Start();
longRunningFunction();
这对我也不起作用。
答案 0 :(得分:1)
你应该可以使用Dispatcher
来做这类事情。 e.g。
Application.Current.Dispatcher.Invoke((Action)(() =>
{
_indicator.Visibility = Visibility.Visible;
}));
这将导致代码在UI-Thread上运行。
CheckAccess
中有更多信息(包括如何"正确"执行此操作,threading model reference等)。
答案 1 :(得分:0)
您无法从后台工作程序访问UI控件。您通常所做的是在调用BackgroundWorker.RunWorkerAync()之前将IsBusy设置为true,然后在BackgroundWorker.RunWorkerCompleted事件处理程序中将IsBusy设置为false。像这样的东西:
Backgroundworker worker = new BackgroundWorker();
worker.DoWork += ...
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
IsBusy = false;
};
IsBusy = true;
worker.RunWorkerAsync();
您可以使用Dispatcher在DoWork事件处理程序中向ObservableCollection添加项目。
编辑:这是完整的解决方案
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();
}