繁体   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