【发布时间】:2020-09-16 10:30:22
【问题描述】:
我正在尝试实现一个响应式搜索文本框,其中搜索结果会随着用户输入搜索文本而更新。我正在尝试使用 Tasks 执行此操作,但我发现有时之前的搜索会在稍后的搜索之后完成,从而将新结果替换为旧结果。
一种快速解决方法是在用户停止输入半秒左右后延迟开始搜索。但是,我认为这只会隐藏问题。我想找到一个通用的解决方案。
到目前为止,我已经提出了以下课程:
public class LastAddedTaskStrategy<T>
{
private DateTime latest;
public T Result { get; private set; }
public async Task Add(Task<T> t)
{
var timestamp = DateTime.Now;
latest = timestamp;
var currentResult = await t;
if (timestamp >= latest)
Result = currentResult;
}
}
这个想法是,您可以添加(和等待)任意数量的任务(例如,搜索),但只有最后添加的(不是最后完成的)任务的结果才能获胜。因此,如果之前的搜索在之后的搜索之后完成,Results 属性将不会更新,因为它是旧结果。
这是一个好的解决方案还是有更好的解决方案?
【问题讨论】:
-
那么当添加一个新任务时,您是否可以取消任何正在运行的任务,因为您只是要丢弃它们的结果?
-
我认为你应该取消旧任务。
-
而不是
DateTime.Now,您可以对Interlocked.Incrementedint/long执行相同的操作 - 以避免DateTime.Now可能对多个@987654329 具有相同值的问题@s. -
@RufusL 我想过这个问题,但我不确定该怎么做。根据 C# Cookbook 中的 Concurrency,即使 Task 被取消,它实际上也有可能成功完成(例如,在请求取消时它可能几乎完成)。
-
@redcurry 当您取消任务时,您可以检查 Task.Status 是否已取消。以这种方式可以忽略取消的任务。查看system.threading.tasks.taskstatus 了解更多信息。
标签: c# asynchronous concurrency async-await task