uwp C#取消异步任务并重新运行

uwp C#取消异步任务并重新运行,c#,uwp,async-await,C#,Uwp,Async Await,提前谢谢。 我想使用foreach将项目添加到“GridView”。这是在异步方法中完成的。 我想从其他异步方法检索项,并在GridView中显示它们: public async Task SetGridItems(CancellationToken ct, /* and some items */) { GridItems.clear(); //get two list of item I want var ListA = await getBmethodAsync(

提前谢谢。 我想使用foreach将项目添加到“GridView”。这是在异步方法中完成的。 我想从其他异步方法检索项,并在GridView中显示它们:

public async Task SetGridItems(CancellationToken ct, /* and some items */)
{

    GridItems.clear();
    //get two list of item I want
    var ListA = await getBmethodAsync().AsTask(ct);
    var ListB = await getAmethodAsync().AsTask(ct);

    foreach (itemA A in ListA)
    {     
        GridItem i = new GridItem();

        //set name
        i.name = A.Name;

        //get icon
        i.image = img;

        GridItems.Add(i);
    }

    foreach (ItemB b in ListB)
    {
         GridItem i = new GridItem();
         i.name = b.Name;
         i.image.SetSource(icon);

         GridItems.Add(i);
    }
}
为方便起见,内容简化了

在按钮单击处理程序中运行此方法时:

private async void check_btn2_Click(object sender, RoutedEventArgs e)
{    
    if (cts != null) { 
        cts.Cancel();
        debug.Text = "cancel a job 4";
    }

    cts = new CancellationTokenSource();
    try
    {
       await SetGridItems(ct.Token, /* and some items */).AsAsyncAction().AsTask(cts.Token);
    }
    catch (OperationCanceledException) { debug.Text = "cancel a job"; }
}
问题是:

如果我两次单击此按钮(快速单击): -第一次单击时,将调用事件回调,我的任务将开始运行 -某些内容将显示在
网格视图中,但不会完成(以80%结束)
-第二次单击时,
GridView
按预期清除,并加载一些新内容,但
GridView
仅显示第一次单击任务的最后20%

那么,为什么第二次单击不取消第一个任务

我在网上搜索了很长时间,努特什么也没找到。请提供帮助并尝试给出一些如何实现这一点的想法


我的英语不好,谢谢

我发现这里有两个问题:

首先,正如Vincent在评论中所说的,您以一种稍微冗余的方式通过
asasacynaction().AsTask(cts.token)传递取消令牌在按钮中单击处理程序和
.AsTask(ct)

第二,也是更重要的一点,您将取消令牌传递给任务,但您从未在方法中使用它。将取消令牌传递给任务主要用于并行工作,而不是异步工作。这是一种协调和查询同时运行的多个任务的执行状态的方法。无论如何,它总是依赖于在执行代码中使用令牌本身。这样想,您告诉任务对象本身您正在取消操作,但您的代码不知道如何处理它

在异步开发中,您实际上不需要将取消传递给任务对象,因为您不必协调其中许多对象的状态,您只需要执行一个。您应该将令牌传递给您的方法,并让您的代码处理它。
因此,在您的
SetGridItems
方法中,尝试执行以下操作:

public async Task SetGridItems(CancellationToken ct, /* and some items */)
{

    GridItems.clear();
    //get two list of item I want
    var ListA = await getBmethodAsync().AsTask(ct);
    var ListB = await getAmethodAsync().AsTask(ct);

    foreach (itemA A in ListA)
    {
        ct.ThrowIfCancellationRequested();

        GridItem i = new GridItem();

        //set name
        i.name = A.Name;

        //get icon
        i.image = img;

        GridItems.Add(i);
    }

    foreach (ItemB b in ListB)
    {
        ct.ThrowIfCancellationRequested();

        GridItem i = new GridItem();
        i.name = b.Name;
        i.image.SetSource(icon);

        GridItems.Add(i);
    }
}
确保在
GetXMethodAsync
方法中执行相同的操作。这样您的代码就知道如何处理取消。因为现在,任务对象可能会被取消,但它仍然会继续执行代码,因为它不知道在哪里停止

有关任务取消的更多信息,请参见以下链接:
1.
2.


希望这有帮助

我在这里看到两个问题:

首先,正如Vincent在评论中所说的,您以一种稍微冗余的方式通过
asasacynaction().AsTask(cts.token)传递取消令牌在按钮中单击处理程序和
.AsTask(ct)

第二,也是更重要的一点,您将取消令牌传递给任务,但您从未在方法中使用它。将取消令牌传递给任务主要用于并行工作,而不是异步工作。这是一种协调和查询同时运行的多个任务的执行状态的方法。无论如何,它总是依赖于在执行代码中使用令牌本身。这样想,您告诉任务对象本身您正在取消操作,但您的代码不知道如何处理它

在异步开发中,您实际上不需要将取消传递给任务对象,因为您不必协调其中许多对象的状态,您只需要执行一个。您应该将令牌传递给您的方法,并让您的代码处理它。
因此,在您的
SetGridItems
方法中,尝试执行以下操作:

public async Task SetGridItems(CancellationToken ct, /* and some items */)
{

    GridItems.clear();
    //get two list of item I want
    var ListA = await getBmethodAsync().AsTask(ct);
    var ListB = await getAmethodAsync().AsTask(ct);

    foreach (itemA A in ListA)
    {
        ct.ThrowIfCancellationRequested();

        GridItem i = new GridItem();

        //set name
        i.name = A.Name;

        //get icon
        i.image = img;

        GridItems.Add(i);
    }

    foreach (ItemB b in ListB)
    {
        ct.ThrowIfCancellationRequested();

        GridItem i = new GridItem();
        i.name = b.Name;
        i.image.SetSource(icon);

        GridItems.Add(i);
    }
}
确保在
GetXMethodAsync
方法中执行相同的操作。这样您的代码就知道如何处理取消。因为现在,任务对象可能会被取消,但它仍然会继续执行代码,因为它不知道在哪里停止

有关任务取消的更多信息,请参见以下链接:
1.
2.


希望这有帮助

仅凭你分享的东西很难猜出发生了什么。乍一看,您的代码似乎是正确的。我唯一关心的是
.asasasyncAction().AsTask(cts.Token)
SetGridItems(ct.Token,/*和一些items*/)之后进行的调用
。如果您已经向该方法提供了取消令牌,则无需通过
AsTask()
再次提供该令牌。这同样适用于您的
getBmethodAsync()
getAmethodAsync()
,您可以直接提供取消令牌,并使用它来执行您需要的操作。我猜外部取消会产生这种副作用。感谢Vincent和CKII的帮助,ct.ThrowIfCancellationRequested();is workedIt很难猜测仅使用您共享的内容会发生什么。乍一看,您的代码似乎是正确的。我唯一关心的是
.asasasyncAction().AsTask(cts.Token)
SetGridItems(ct.Token,/*和一些items*/)之后进行的调用
。如果您已经向该方法提供了取消令牌,则无需通过
AsTask()
再次提供该令牌。这同样适用于您的
getBmethodAsync()
getAmethodAsync()
,您可以直接提供取消令牌,并使用它来执行您需要的操作。我猜外部取消会产生这种副作用。感谢Vincent和CKII的帮助,ct.ThrowIfCancellationRequested();非常感谢,这是工作!!!:),谢谢,代码不知道如何处理它,这就是问题所在。非常感谢,这是工作!!!:),谢谢,代码不知道如何处理它,这就是问题所在。