在here之前已经问过这个问题,但答案只是“使用BackgroundWorker”,我问的是否有完整的代码示例可用。
我想创建一个与计时器配合使用的标准AutocompleteTextBox,这样只有一个BackgroundWorker正在搜索 - 如果用户输入了几个键击,但旧搜索仍在运行 - 那么搜索应该是取消gracefuly(通过CancelAsync),一旦取消,新搜索将开始。
实现起来并不是那么简单 - 是否有任何代码示例?
答案 0 :(得分:3)
我怀疑你会找到一个代码示例来帮助你解决你在这里讨论的具体问题。这是我如何做到这一点。这些代码都没有经过测试,所以要小心愚蠢的错误。
首先,子类TextBoxBase
并添加两个基本方法来实现搜索逻辑,具有以下签名:
private IEnumerable<string> PerformSearch(string text)
private DisplayResults(IEnumerable<string> results)
向该类添加名为BackgroundWorker
的私有Worker
字段,并将其DoWork
和RunWorkerCompleted
事件设置为名为Worker_DoWork
和{{1}的事件处理程序}。
覆盖Worker.RunWorkerCompleted
:
OnTextChanged
public override void OnTextChanged(TextChangedEventArgs e)
{
base.OnTextChanged(e);
// if we're already cancelling a search, there's nothing more to do until
// the cancellation is complete.
if (Worker.CancellationPending)
{
return;
}
// if there's a search in progress, cancel it.
if (Worker.IsBusy)
{
Worker.CancelAsync();
return;
}
// there's no search in progress, so begin one using the current value
// of the Text property.
Worker.RunWorkerAsync(Text);
}
事件处理程序非常简单:
Worker_DoWork
private void Worker_DoWork(object sender,
RunWorkerCompletedEventArgs e)
{
e.Result = PerformSearch((string) e.Argument);
}
事件处理程序如下所示:
Worker_RunWorkerCompleted
请注意private void Worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
// always check e.Error first, in case PerformSearch threw an exception.
if (e.Error != null)
{
// in your version, you want to do real exception handling, not this.
throw e.Error.InnerException;
}
// if the worker was cancelled, it's because the user typed some more text, and
// we want to launch a new search using what's currently in the Text property.
if (e.Cancelled)
{
Worker.RunWorkerAsync(Text);
return;
}
// if the worker wasn't cancelled, e.Result contains the results of the search.
DisplayResults((IEnumerable<string> e.Result);
}
应该测试它对文本框状态的任何假设。例如,当用户启动搜索时,文本框可能已被显示或启用,而现在不可见或未启用。如果在模式对话框中使用此文本框并且用户在搜索运行时取消对话框会发生什么?
另请注意,如果您的应用程序中有多个此控件实例,则每个实例将具有不同的DisplayResults
,因此BackgroundWorker
方法必须是线程安全的。如果不是,它将必须实现锁定,因此如果您在一个文本框中启动搜索,它会阻止并等待另一个文本框当前正在使用共享资源。
答案 1 :(得分:0)
我建议使用System.Windows.Forms.TextBox
中的AutoComplete功能。您可以自定义它并围绕此构建完成内容。
注意:AutoComplete功能仅适用于.NET 2.0