我尝试在另一个线程上添加加载数据模型并将项目加载到列表框,因为将50个项目加载到列表框需要很长时间(约5秒)。
我遇到BackgroundWorker的问题,它向我显示错误无效的跨线程访问
他是Inbox.xaml的代码
public Inbox()
{
InitializeComponent();
DataContext = App.ViewModel;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ProgressIndicator progress = new ProgressIndicator
{
IsVisible = true,
IsIndeterminate = true,
Text = "Načítání"
};
SystemTray.SetProgressIndicator(this, progress);
SystemTray.IsVisible = true;
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
backgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
LoadData();
}
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else
{
SystemTray.IsVisible = false;
}
}
private void LoadData()
{
try
{
(this.DataContext as MainViewModel).LoadInboxData();
}
finally
{
TasksListBox.ItemsSource = (this.DataContext as MainViewModel).Tasks;
}
}
我做错了什么?
答案 0 :(得分:2)
BackgroundWorker.DoWork处理程序在后台非ui线程上运行。在您的示例中,LoadData()方法在后台非ui线程上运行,并且您正在该方法中设置ListBox的ItemSource属性。
您应该尝试将该代码移动到BackgroundWorkder.RunWorkerCompleted处理程序,因为此处理程序在UI线程上运行。
您的代码可以像下面一样重写,以避免错误:
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else
{
SystemTray.IsVisible = false;
TasksListBox.ItemsSource = (this.DataContext as MainViewModel).Tasks;
}
}
private void LoadData()
{
(this.DataContext as MainViewModel).LoadInboxData();
}
答案 1 :(得分:1)
您正在尝试从非UI线程更新UI,因此您将获得异常。
只有UI线程可以执行UI更新,您需要使用Dispatcher
才能从非UI线程更新UI。
Dispatcher.BeginInvoke(() =>
{
// Update UI in here as this part will run on the UI thread.
});
请参阅:http://msdn.microsoft.com/en-gb/library/system.windows.threading.dispatcher.begininvoke.aspx