我遇到问题,使用(任务并行库)将WPF ListView绑定更新为任务线程中的ObservableCollection<T>
我有一个小工具读取Edifact个文件,并显示每个段的计数(一行的前三个字母)。
包含的细分及其计数显示在列表框中。
Wenn我最初加载文件一切正常,我看到GUI计算细分。 我的程序允许切换到另一个文件,如果我这样做(使用完全相同的代码),它会导致以下异常。
这种类型的CollectionView不支持从与Dispatcher线程不同的线程更改其SourceCollection。
以下是失败的代码
public class SegementLineCollection : ObservableCollection<SegmentLine>
{
public void IncrementCount(string Segment)
{
Segment = Segment.ToUpper();
SegmentLine line;
if (this.Select(x => x.SegmentName).Contains(Segment))
{
line = this.Where(x => x.SegmentName == Segment).FirstOrDefault();
}
else
{
line = new SegmentLine();
line.SegmentName = Segment;
this.Add(line); // <--- At this point comes the Exception
}
line.Count++;
}
}
以下是我使用的TPL呼叫:
private string _FileName;
public string FileName
{
get
{
return _FileName;
}
set
{
_FileName = value;
OnPropertyChanged("FileName");
if (!String.IsNullOrEmpty(value))
new Task(() => StartFile()).Start();
}
}
有没有人对我有任何打击?
------------ E D I T ------------------
使用TaskScheduler.FromCurrentSynchronizationContext()或Dispatcher提供的Answers没有使用Trick!
加载新版本时更改Binding是否有可能成功。
以下是我使用的Binding,在ViewModel中使用Reader Onject进行切换,并使用INotifyPropertyChanged实现GUI进行Notfied
答案 0 :(得分:1)
使用调度程序访问集合:
if (Dispatcher.CurrentDispatcher.CheckAccess())
this.Add(...)
else
Dispatcher.CurrentDispatcher.Invoke(() => this.Add(...));
答案 1 :(得分:1)
您需要在GUI线程上调用IncrementCount。
使用TPL,您可以在任务或续课中使用TaskScheduler.FromCurrentSynchroniztionContext()
。
var task = new Task<string>(() => { return "segment"; })
var task2 = task.ContinueWith(t => IncrementCount(t.Result),
TaskScheduler.FromCurrentSynchroniztionContext());
task.Start();
答案 2 :(得分:0)
当您在不同的线程上执行操作时,您需要使用Dispatcher.BeginInvoke
对绑定到UI
的集合运行更新
答案 3 :(得分:-2)
我在以下博客中找到了解决此类问题的方法..
http://bathinenivenkatesh.blogspot.co.uk/2011/07/wpf-build-more-responsive-ui.html
它得到了详细的解释和代码片段......