簡體   English   中英

中止ado.net查詢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM