使用第二个线程访问域模型

时间:2017-02-07 22:31:54

标签: c# multithreading collections

我的域模型是由应用程序修改的大型树结构。我想在BackgroundWorker中实现搜索(单独的线程不阻止UI)。

目前使用ObservableCollection实现树结构,在修改时无法枚举,因此如果用户在搜索树时修改了树,我的搜索将失败。

这个问题的优雅解决方案是什么?我的要求:不要阻止用户做任何事情(操作应该是异步的),在单独的线程上搜索(以加快速度)。

1 个答案:

答案 0 :(得分:0)

这是我能想到的一种方法,你可以实现你所需要的:

  1. 编写时,使用lock,创建集合的副本,添加到副本,然后将集合重新分配给副本。
  2. 以下是一些代码,您可以测试上述方法。创建一个包含ListBoxButton的表单。在线程上搜索列表时,您可以使用按钮将项目添加到列表中。

    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;