uwp C#取消异步任务并重新运行
提前谢谢。 我想使用foreach将项目添加到“GridView”。这是在异步方法中完成的。 我想从其他异步方法检索项,并在GridView中显示它们: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(
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();非常感谢,这是工作!!!:),谢谢,代码不知道如何处理它,这就是问题所在。非常感谢,这是工作!!!:),谢谢,代码不知道如何处理它,这就是问题所在。