我正在实施自动完成控件。每次用户在输入中键入新字符时,都会触发查询。为了测试,我创建了一个大型数据库,其中平均查询大约需要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有时会导致异常,有时则会导致异常......
答案 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" );
}
}