中止ado.net查询

时间:2012-03-15 07:17:57

标签: c# multithreading linq ado.net

我正在实施自动完成控件。每次用户在输入中键入新字符时,都会触发查询。为了测试,我创建了一个大型数据库,其中平均查询大约需要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是绑定到我的文本框和列表的属性。

问题是如果用户键入两个字符,我的程序将同时运行两个线程。我该如何中止查询?


我正在考虑的事情:

创建一个bool变量IsQueryRuning并将其设置为等于true,当线程结束时,查询开始并等于false。如果将执行一个新查询并且IsQueryRuning = true,那么我可以设置ObservableCollection = null并导致一个exeption。然后我将使用try catch块重新调整它。我认为这种技术不是最好的方法..


编辑:

设置属性Collection = null有时会导致异常,有时则会导致异常......

3 个答案:

答案 0 :(得分:1)

我建议采用不同的方法,如果可以为你改变的话。

我只会在例如3个字符后进行查询,而不是查询用户的每次击键。将结果保存在内存中的某些集合中。

之后,只对内存中的集合进行下一次查询。这样可以避免任何后续数据库访问,这些访问总是慢得多,并且应该获得相当大的性能提升。

答案 1 :(得分: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;
        }
    }

答案 2 :(得分: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" );
    }
}