【发布时间】:2014-01-27 20:55:40
【问题描述】:
如何处理用户可能多次点击按钮的情况,这会调用长时间运行的异步操作。
我的想法是首先检查异步操作是否正在运行,取消它并再次触发它。
到目前为止,我已经尝试使用 CancellationTokenSource 构建这种功能,但它没有按预期工作。有时会运行两个异步操作,因此当我启动新的异步操作时,“旧”异步操作尚未取消,这会混淆结果处理。
有什么建议或例子如何处理这种情况?
public async void Draw()
{
bool result = false;
if (this.cts == null)
{
this.cts = new CancellationTokenSource();
try
{
result = await this.DrawContent(this.TimePeriod, this.cts.Token);
}
catch (Exception ex)
{}
finally
{
this.cts = null;
}
}
else
{
this.cts.Cancel();
this.cts = new CancellationTokenSource();
try
{
result = await this.DrawContent(this.TimePeriod, this.cts.Token);
}
catch (Exception ex)
{}
finally
{
this.cts = null;
}
}
}
编辑: 最后,我认为在短时间内运行两个异步操作(当新操作被触发但旧操作尚未取消时)也不错。
这里真正的问题是我如何为最终用户显示进度。当旧的异步操作结束时,它会向最终用户隐藏进度指示器,但新触发的异步操作仍在运行。
编辑2: 在 DrawContent(...) 中,我使用 ThrowIfCancellationRequested,因此取消正在运行的任务似乎可以正常工作。
关于进度显示。调用 Draw() 时,我将加载指示器设置为可见,当此方法结束时,我隐藏加载指示器。所以现在当我开始新的异步操作后取消之前的异步操作时,我的加载指示器被设置为隐藏。当“旧”方法结束时,如果还有另一种异步方法仍在运行,我应该如何跟踪。
【问题讨论】:
-
如何它不起作用。不要只是说 它不起作用。当然,吞下所有异常通常是个坏主意。不要那样做。当你这样做时,你永远不会知道出了什么问题。
-
当然,旧的仍然可以运行。您永远不会等到前一个操作完成后再继续。如果在请求取消和任务完成之间有一段时间,那么将有两个作业在这段时间内运行。
-
@devha,这取决于您如何显示进度。是对话吗?
-
再次更新问题:)
-
@devha,更新了答案。
标签: c# asynchronous windows-phone-8 async-await cancellationtokensource