【问题标题】:Visit domain model with second thread使用第二个线程访问域模型
【发布时间】:2017-06-25 08:55:10
【问题描述】:
我的域模型是由应用程序修改的大树结构。我想在 BackgroundWorker 中实现搜索(单独的线程不阻塞 UI)。
目前树结构是用 ObservableCollection 实现的,在修改时无法枚举,所以如果用户在我搜索时修改树,我的搜索将失败。
这个问题的优雅解决方案是什么?我的要求:不要阻止用户做任何事情(操作应该是异步的),在单独的线程上搜索(以加快速度)。
【问题讨论】:
标签:
c#
multithreading
collections
【解决方案1】:
这是我能想到的一种可以实现所需的方法:
- 写的时候,使用
lock,创建集合的副本,添加到副本中,然后将集合重新分配给副本。
这里有一些代码,您可以测试上述方法。使用ListBox 和Button 创建一个表单。在线程上搜索列表时,您可以使用按钮将项目添加到列表中。
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
namespace WindowsForms {
public partial class Form1 : Form {
object key = new object();
private List<string> items;
public Form1() {
InitializeComponent();
items = new List<string>();
for( int i = 0; i < 100000; i++ ) {
this.items.Add( i.ToString() );
}
this.listBox1.DataSource = this.items;
}
private void Read() {
foreach( var thisItem in this.items ) {
if (thisItem.ToString() == "100000" ) {
MessageBox.Show( "Found" );
}
else {
Thread.Sleep( 100 );
}
}
}
private void buttonStation2_Click(object sender, EventArgs e) {
lock( this.key ) {
var copy = new List<string>( this.items );
copy.Add( "1000001" );
this.items = copy;
}
}
private void Form1_Shown(object sender, EventArgs e) {
Thread reader = new Thread( Read );
reader.Start();
}
}
}
您可能还想使集合变量volatile 不使用缓存版本,并且您在阅读时始终获得最新版本。但是,您确实需要在使用 volatile 关键字之前知道它的作用,这就是为什么我没有在我的代码中使用它并让您决定的原因。此外,如果其他 SO 用户愿意,可以使用 cmets 中的volatile 加入并提供他们的建议。
private volatile List<string> items;