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