2012-03-15 72 views
0

我正在實現一個自動完成控件。每次用戶在輸入中鍵入新字符時,查詢都會觸發。爲了測試,我創建了一個大型數據庫,其中平均查詢大約需要5秒鐘執行。中止ado.net查詢

因爲查詢需要5秒鐘,執行我執行查詢的一個新的線程:

// execute the following lamda expression when user enters characters to textbox 
    textBox1.TextChanged +=(x,eventArgs)=>{ 

      // execute query on separate thread 
      new Thread(new ThreadStart(() => 
      { 
       ObservableCollection = MyEntities.Entities.Products.Where(p => p.Name.Contains(inputText)); 
      })).Start(); 
    }; 

的ObservableCollection和inputText的是綁定到我的文本框和列表屬性。

問題是,如果用戶鍵入兩個字符,我的程序將同時運行兩個線程。我如何中止查詢?


的事情,我在想:

創建一個布爾變量IsQueryRuning並設置它等於真正quen查詢開始,當線程結束等於假。如果一個新的查詢將被執行並且IsQueryRuning = true,那麼我可以設置ObservableCollection = null並導致一個exeption。然後,我會用try catch塊重新調用它。我認爲,技術是不是最好的方法..


編輯:

設置屬性集合= NULL有時會導致一個例外,它沒有一些其他時間...

回答

1

我會建議一種不同的方法,如果這可能會改變你。

而不是查詢用戶的每個按鍵,我只會在例如3個字符後執行查詢。將結果保存在內存中的某些集合中。

之後,只對內存中的集合執行下一個查詢。這樣可以避免任何後續數據庫訪問總是慢得多,並且應該獲得相當大的性能提升。

0

我不得不執行查詢如:

public IEnumerable<T> ExecuteQuery(IEnumerable<T> query) 
    { 
     foreach (var t in query) 
     { 
      if (counterOfSymultaneosQueries > 1) 
      { 
       // if there are more than two queries break from the last one 
       // breaking from it will decrease counterOfSymoltanosQueries 
       break; 
      } 
      yield return t; 
     } 
    } 
0
class Program 
{   
    public class Person 
    { 
     public string Name; 
     public int Age; 
    }   

    public static void ExecuteQueryAsync (IEnumerable<Person> collectionToQuery , Action<List<Person>> onQueryTerminated , out Action stopExecutionOfQuery) 
    { 
     var abort = false; 

     stopExecutionOfQuery =() => 
     { 
      abort = true; 
     };    

     Task.Factory.StartNew(() => 
     { 
      try 
      { 
       var query = collectionToQuery.Where(x => 
       { 
        if (abort) 
         throw new NotImplementedException("Query aborted"); 

        // query logic: 
        if (x.Age < 25) 
         return true; 
        return 
         false; 
       }); 

       onQueryTerminated(query.ToList()); 

      } 
      catch 
      { 
       onQueryTerminated(null); 
      } 
     }); 
    } 


    static void Main (string[] args) 
    { 
     Random random = new Random(); 

     Person[] people = new Person[ 1000000 ]; 

     // populate array 
     for (var i = 0 ; i < people.Length ; i++) 
      people[ i ] = new Person() { Age = random.Next(0 , 100) }; 

     Action abortQuery; 
     ExecuteQueryAsync(people , OnQueryDone , out abortQuery); 

     // if after some time user wants to stop query: 
     abortQuery(); 

     Console.Read(); 
    } 

    static void OnQueryDone (List<Person> results) 
    { 
     if (results == null) 
      Console.WriteLine("Query was canceled by the user"); 
     else 
      Console.WriteLine("Query yield " + results.Count + " results"); 
    } 
}