提前致谢。 我想使用foreach将项添加到`GridView。这是在 async 方法中完成的。 我想从其他 async 方法中检索项目并在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"; }
}
问题在于:
如果我点击此按钮两次(快速点击):
- 第一次单击时,将调用事件回调,我的任务将开始运行
- 某些内容会在GridView
中显示但不会完成(结束时为80%)
- 第二次点击时,GridView
按预期清除,并加载了一些新内容,但GriView
仅显示第一次点击任务的最后20%
那么,为什么第二次点击不取消第一个任务?
我在网上搜了很久,坚果没找到任何东西。请帮助并尝试提供一些如何实现这一目标的想法。
我不擅长英语,谢谢
答案 0 :(得分:1)
我在这里看到两个问题:
首先,正如文森特在评论中所说,您通过按钮点击处理程序中的AsAsyncAction().AsTask(cts.Token);
和方法本身中的.AsTask(ct);
以一种多余的方式传递取消令牌。 / p>
其次,更重要的是,您将取消令牌传递给任务,但您从未在该方法中使用它。将取消令牌传递给任务主要是并行使用,而不是异步工作。它是您协调和查询一次运行的多个任务的执行状态的一种方式。无论如何,它始终依赖于令牌本身在执行代码中的使用。可以这样想,你告诉任务对象本身你取消了操作,但你的代码并不知道如何处理它。
在异步开发中,你真的不需要将取消传递给任务对象,因为你不必协调其中许多的状态,你只是执行一个。您应该将令牌传递给您的方法,并让您的代码处理它
因此,在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. https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-cancellation
2. https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-cancel-a-task-and-its-children
希望这有帮助