[英]Abort ado.net query
我正在實現自動完成控制。 每次用戶在輸入中輸入新字符時,都會觸發查詢。 為了進行測試,我創建了一個大型數據庫,平均查詢執行時間約為5秒。
因為查詢需要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並將其設置為等於真隊列查詢開始,並等於線程結束時為false。 如果將執行一個新查詢並且IsQueryRuning = true,那么我可以將ObservableCollection = null設置為異常。 然后,我將使用try catch塊將其解決。 我認為該技術不是最佳方法。
編輯:
設置屬性Collection = null有時會導致異常,而有時不會。
如果可以為您帶來改變,我建議您采用其他方法。
而不是查詢用戶的每次擊鍵,我只會在例如3個字符之后進行查詢。 將結果保存在內存中的某個集合中。
之后,僅對內存集合進行下一個查詢。 這樣可以避免您以后進行的任何數據庫訪問,這些訪問總是慢得多,並且您應該獲得可觀的性能提升。
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" );
}
}
我必須像執行查詢:
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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.