c# - 在重入调用上使用异步方法时如何处理 WPF 中的忙指示符?
问题描述
在 WPF 控件(例如网格)中,我们通常可以设置一个布尔属性来显示控件正忙于加载数据,并且在 UI 中这将导致“正在加载...”指示器。
使用async
方法时,我们只需要确保IsBusy = "true"
在调用方法之前和IsBusy="false"
调用await
.
但是,如果我可以在第一次调用完成时多次调用网格加载方法,即使第二次调用正在进行,它也会关闭忙碌指示器。
有什么办法可以解决这个问题?我可以设置一个全局计数器来存储请求的数量,并根据这个全局变量的计数设置指标的状态,但它是一种肮脏的方法,如果我的代码中有多个异步事件,它就不会扩展。
示例场景
在下图中,我可以搜索学生的姓名,对于每个姓名,我的服务将获取详细信息(标记等)并将其显示在第二个网格中。
我想在第二个网格等待数据时显示一个繁忙的指示器(否则用户可能不知道程序是否在做任何事情)。
在输入名称时,将调用以下方法:
想象GetStudentResults
需要 5 秒(每次通话)。我在 0 秒输入名字,然后在 3 秒输入另一个名字。现在在 5 秒时,第一个呼叫返回并且它关闭忙指示符,而第二个姓名详细信息不会被检索。这是我想要避免的。
private async void SearchName(string name)
{
ResultDisplayGrid.IsBusy = true;
await GetStudentResults();
ResultDisplayGrid.IsBusy = false;
}
解决方案
自最新评论以来考虑到这一点,它将需要一个更复杂的解决方案,涉及适当的任务管理,这在帮助他人时开始超出我的舒适区。
在我看来,最快和最简单的方法是在搜索开始后阻止用户与文本框或 GUI 进行交互,从而在前一个搜索完成之前阻止其他搜索。这当然意味着用户需要等待每个搜索完成,然后才能开始下一个搜索。
我的下一个方法是存储 GetStudentResults 任务并使用 CancellationToken。例如 SearchName 可能变成:
private CancellationTokenSource ctsSearch;
private Task tSearch;
private async void SearchName(string name)
{
if(ctsSearch != null)
{
ctsSearch.Cancel();
if(tSearch != null)
await tSearch;
}
ctsSearch = new CancellationTokenSource();
ResultDisplayGrid.IsBusy = true;
tSearch = GetStudentResults(ctsSearch.Token);
await tSearch;
ResultDisplayGrid.IsBusy = false;
}
在上面的代码中,我们在尝试再次运行 GetStudentResults 之前取消了之前的任务。在您的 GetStudentResults 方法中,您需要找到可以插入的位置:
if(token.IsCancellationRequested)
return Task.FromResult(false); //Replace this return type with whatever suits your GetStudentResults return type.
我的 GetStudentResults 方法是:
private Task<bool> GetStudentResults(CancellationToken token)
{
for(int i = 0; i < 10000; i++)
{
if (token.IsCancellationRequested)
return Task.FromResult(false);
Console.WriteLine(i);
}
return Task.FromResult(true);
}
有人可能有其他想法,但对我来说,这些是最简单的方法。
推荐阅读
- java - 使用 ParallelFlux 时限制最大线程数
- vue.js - 尝试进行慢速滚动,但似乎 gsap 无法处理每个滚动的尽可能多的事件
- java - 编辑 JTable 后获取选定的行和列
- css - Bootstrap 中有多个进度条,左侧标签向右推
- python - keras - tensorflow错误地使用GPU,没有使用它的所有内存
- java - 如何舍入此代码中打印的星号数量?
- python - 在 Dataframe 中的两列之间为所有日期添加行的快速方法
- c++ - (structname/classname) does not name a type C++
- flutter - Flutter android studio 导入包路径
- amazon-s3 - Camel S3:在调度程序关闭的情况下列出 S3 存储桶文件