我的域模型是由应用程序修改的大型树结构。我想在BackgroundWorker中实现搜索(单独的线程不阻止UI)。
目前使用ObservableCollection实现树结构,在修改时无法枚举,因此如果用户在搜索树时修改了树,我的搜索将失败。
这个问题的优雅解决方案是什么?我的要求:不要阻止用户做任何事情(操作应该是异步的),在单独的线程上搜索(以加快速度)。
答案 0 :(得分:0)
这是我能想到的一种方法,你可以实现你所需要的:
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用户可以在评论中使用volatile
来加入并提供他们的建议。
private volatile List<string> items;