C# 取消异步操作
如果用户敲打C# 取消异步操作,c#,wpf,multithreading,cancellationtokensource,C#,Wpf,Multithreading,Cancellationtokensource,如果用户敲打Change\u Week按钮,我如何取消当前任务,并使用新参数启动新任务 我试着这样做: private async void TriggerWeekChanged(Week currentWeek) { await LoadDataForSelectedWeek(currentWeek); //Split into multiple methods } 问题是: 在我的收藏中当我连续按“快速”按钮时,我获得了数周的数据。您没有提到为所选周加载数据和刷新如何交互 简而言
Change\u Week
按钮,我如何取消当前任务,并使用新参数启动新任务
我试着这样做:
private async void TriggerWeekChanged(Week currentWeek)
{
await LoadDataForSelectedWeek(currentWeek); //Split into multiple methods
}
问题是:
在我的
收藏中
当我连续按“快速”按钮时,我获得了数周的数据。您没有提到为所选周加载数据
和刷新
如何交互
简而言之,您需要创建一个CancellationTokenSource
实例来处理每次单击。然后将其传递给该方法,并在每次出现新方法时执行Cancel
method
private async Task Refresh(Week selectedWeek, CancellationToken token)
{
Collection.Clear();
await LoadDataFromDatabase();
token.ThrowIfCancellationRequested();
await ApplyDataToBindings();
token.ThrowIfCancellationRequested();
//Do some other stuff
}
LoadDataForSelectedWeek->刷新(?)
等待的一切都需要在该
取消令牌上具有可见性。如果它是您编写的自定义任务
,它应该接受它作为参数,并定期在函数中检查它是否已被取消。如果是这样,它应该采取所需的任何操作(如果有)来停止或回滚正在进行的操作,然后通过wifcancellationrequest()调用
在示例代码中,您可能希望将令牌
传递到LoadDataFromDatabase
和ApplyDataToBindings
,以及这些任务的任何子任务
在某些更高级的情况下,您可能不想将相同的CancellationToken
传递给子任务,但仍然希望它们是可取消的。在这些情况下,您应该为用于子任务的任务
,取消令牌
创建一个新的内部令牌
需要记住的一点是,ThrowIfCancellationRequested
标记了任务中可以停止任务的安全位置。运行时无法保证安全地自动检测安全位置。如果任务
在请求取消时自动取消其自身,则它可能处于未知状态,因此由开发人员标记这些安全位置。在整个任务中,有几个检查取消的调用分散在一起,这并不少见
我刚刚注意到您的TriggerWeekChanged
函数是async void
。当它用于非事件处理程序的对象时,通常被认为是反模式。在跟踪方法中的async
操作的完成状态以及处理可能从方法中引发的任何异常时,它可能会导致很多问题。您应该对标记为async void
的任何不是事件处理程序的东西感到厌倦,因为在99%或更多的时间里这样做是错误的。我强烈建议将其更改为<代码>异步任务,并考虑从您的其他代码中传递<代码>取消EngultTyp> <代码>。您应该粘贴Load DATA FrExcRead星期和取消代码的全部方法。我注意到您的<代码> TrutGeRealMexEng/<代码>方法是<代码>异步空隙< /代码>。请看一看我在答案末尾添加的注释。@BradleyUffner这是我在提出问题时犯的一个错误。在我的代码中,它的类型是Task
。谢谢你的提醒Task.WaitAll
不是一个选项,因为它完全阻塞了我的UI线程。。。这就是为什么我使用了async/await
,然后我会寻找全局Thread
并将TriggerWeekChanged
中的所有内容发送到那里。或者,如果您不需要//Refresh Passed
中的代码,并且您完全知道将这些方法发送给其他未经验证的任务的后果,那么您可以简单地删除任务。WaitAll
@Erexo不需要这样的回归。您可以使用wait Task.WhenAll()
。此外,asynchronous
并不意味着涉及后台线程。真正的异步IO操作不使用线程。事实上,Task.WaitAll
只会扼杀问题的主要目的。执行时,任务无法终止,因为由于Task.WaitAll
private async void TriggerWeekChanged(Week currentWeek, CancellationTokenSource tokenSource)
{
tokenSource.Cancel();
try
{
var loadDataTask = Task.Run(() => LoadDataForSelectedWeek(currentWeek, tokenSource.Token), tokenSource.Token); //Split into multiple methods
}
catch(OperationCanceledException ex)
{
//Cancelled
}
}
private async Task Refresh(Week selectedWeek, CancellationToken token)
{
Collection.Clear();
await LoadDataFromDatabase();
token.ThrowIfCancellationRequested();
await ApplyDataToBindings();
token.ThrowIfCancellationRequested();
//Do some other stuff
}