Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 取消异步操作_C#_Wpf_Multithreading_Cancellationtokensource - Fatal编程技术网

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
}