Rob*_* J. 6 c# wpf datagrid multithreading mvvm
我有一个绑定的DatGrid var Result_Full = new ObservableCollection<IP_DataRow>()
.这是一个包含多个字符串和双变量的简单类.没什么难的.
我所做的是,我读了一个Excel文件(使用Telerik RadSpreadProcessing),它将行解析到我的类中.我在一个线程上执行此操作,以便不阻止UI.我遇到了一些问题:
1)我不能ref
在读取excel文件的长进程中使用关键字(因为Result_Full是绑定到DataGrid的公共属性),但是我必须创建临时ObservableCollection<IP_DataRow>()
值,其中放置值.完成该过程后,我运行以下脚本来复制值:
foreach (var item in tmpFull)
{
InvokeOnUIThread(() =>
{
Result_Full.Add(item);
});
}
Run Code Online (Sandbox Code Playgroud)
我想做的是,能够实时查看(如果可能)如何将项目添加到我的DataGrid中的集合中.
当我使用.Net 4.5时,我尝试BindingOperations.EnableCollectionSynchronization
按照其他帖子的建议实现,但我无法弄清楚如何将我的UI模型集合Result_Full绑定到进程中临时使用的.
2)即使使用当前设置,当我(在我的UI下)移动到包含DataGrid的我的Tab(我的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;
}
Run Code Online (Sandbox Code Playgroud)
在这里你可以看到,我必须创建临时集合tmpError,tmpFull,我收集我的数据.在进程结束时,我手动将值复制到绑定到DataGrid的主集合中.我想改变这一点,这意味着在过程中将值复制到主集合(而不是临时集合),以便用户可以实时查看如何将值添加到集合中.
PS2:因为我不明原因,我的InvokeOnUIThread
电话中出现了一个问题.一旦我改变App.Current.Dispatcher.Invoke(action);
为App.Current.Dispatcher.BeginInvoke(action);
错误与... 不同的线程拥有它停止.
Application.Current.Dispatcher
代替简而言之,我相信你应该做到以下几点:
(sender as BackgroundWorker).ReportProgress
方法,传入事件args这个你已经填充的集合.