我有一个DatGrid,它绑定到var Result_Full = new ObservableCollection<IP_DataRow>()
。这是一个简单的类,包含几个字符串&双变量。没什么困难。从后台更新ObservableCollection工作人员
我所做的是,我读了一个Excel文件(使用Telerik RadSpreadProcessing),它将行分析到我的类中。我在一个线程上这样做,以便UI不被阻塞。我遇到了一些问题,但:
1)我不能使用ref
关键字在一个很长的过程中读取excel文件(因为Result_Full是绑定到DataGrid的公共属性),但我必须创建临时ObservableCollection<IP_DataRow>()
,其中值被放置。一旦这个过程完成后我运行下面的脚本复制值:
foreach (var item in tmpFull)
{
InvokeOnUIThread(() =>
{
Result_Full.Add(item);
});
}
我想什么做的,是能够在实时(如果可能的话)的项目是如何被加入到看我的DataGrid中的集合。
由于我使用.NET 4.5我试图执行BindingOperations.EnableCollectionSynchronization
这已在一些其他职位的建议,但我无法弄清楚如何我的UI鲍尔德收集Result_Full绑定到临时使用的一个过程。
2)即使使用当前设置,当(在我的UI下)我移动到包含DataGrid(我的DataGrid在不同的TabPage上)的Tab中,并且尝试使用上面提到的将新项添加到集合中代码,它返回一个错误说:调用线程不能访问此对象,因为不同的线程拥有它。,这很奇怪,因为InvokeOnUIThread没有别的,只有Dispatcher.Invoke()
,应该是线程安全的?
任何帮助将不胜感激。
编辑:显示更多的代码:
这是我从BackgroundWorker的调用过程:
public void ProcessFile()
{
var tmpError = new ObservableCollection<IP_DataRow>();
var tmpFull = new ObservableCollection<IP_DataRow>();
var _reader = new IP_ExcelReader(sExcelPath, ref tmpError, ref tmpFull);
string sResult = _reader.ReadExcelFile();
if (sResult != string.Empty)
{
System.Windows.MessageBox.Show("Error processing selected Excel File!" + Environment.NewLine + Environment.NewLine + "Error message:" + Environment.NewLine + sResult);
}
foreach (var item in tmpError)//populates error list
{
IP_InvokeOnUIThread(() =>
{
Result_Error.Add(item);
});
}
foreach (var item in tmpFull)//populates full list
{
IP_InvokeOnUIThread(() =>
{
Result_Full.Add(item);
});
}
OnPropertyChanged("Result_Full");
//OnPropertyChanged("Result_Error");
iSelectedTabIndex = 1;
}
在这里你可以看到,我必须创建临时收集tmpError,tmpFull在那里我收集我的数据。在过程结束时,我手动将值复制到绑定到DataGrid的主集合中。我想对此进行更改,这意味着在过程中将值复制到主集合(不是临时集合),以便用户可以实时查看向集合中添加值的方式。
P.S.2: 因为我不知道的原因,其中一个问题在我的InvokeOnUIThread
调用中。一旦我从App.Current.Dispatcher.Invoke(action);
更改为App.Current.Dispatcher.BeginInvoke(action);
错误..不同线程拥有它停止。
哪个线程拥有'item'和'tmpFull'? – Pieter21
*哪个调度程序?* Dispatcher.Current保存在TLS中,因此每个线程都有自己的调度程序。您需要访问UI线程的调度程序。 – Will
我正在使用** App.Current.Dispatcher.Invoke(action); **。我虽然这是UI调度员?那么我如何访问它? –