【发布时间】:2015-09-17 14:21:49
【问题描述】:
我有一个绑定到var Result_Full = new ObservableCollection<IP_DataRow>() 的DatGrid。这是一个包含多个 string & double 变量的简单类。没什么难的。
我所做的是读取一个 Excel 文件(使用 Telerik RadSpreadProcessing),它将行解析到我的类中。我在一个线程上执行此操作,以便 UI 不会被阻塞。不过我遇到了一些问题:
1) 我不能在读取 excel 文件的长过程中使用 ref 关键字(因为 Result_Full 是绑定到 DataGrid 的公共属性),但我必须创建临时的 ObservableCollection<IP_DataRow>() 来放置值。该过程完成后,我运行以下脚本来复制值:
foreach (var item in tmpFull)
{
InvokeOnUIThread(() =>
{
Result_Full.Add(item);
});
}
我想做的是能够实时(如果可能的话)查看项目是如何添加到我的 DataGrid 中的集合中的。
当我使用 .Net 4.5 时,我尝试按照其他帖子的建议实现 BindingOperations.EnableCollectionSynchronization,但我无法弄清楚如何将我的 UI bould 集合 Result_Full 绑定到临时使用的一个过程。
2) 即使使用当前设置,当(在我的 UI 下)我移动到包含 DataGrid 的选项卡(我的 DataGrid 位于不同的 TabPage 上)时,我尝试使用上述代码将新项目添加到集合中,它返回一个错误说:调用线程无法访问这个对象,因为另一个线程拥有它。,这很奇怪,因为 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'?
-
哪个调度器? Dispatcher.Current 保存在 TLS 中,因此每个线程都有自己的调度器。您需要访问 UI 线程的调度程序。
-
我正在使用 App.Current.Dispatcher.Invoke(action);。我虽然那是 UI 调度程序?那我该如何访问呢?
-
foreach 调用在后台 Worker 中执行
标签: c# wpf multithreading mvvm datagrid