如何取消任务C#
我有一个任务,它从Web服务检索一些数据。只有当我打开一个页面(这是Xamarin.Forms)时,才应该调用Webservice,并且只有在没有其他版本的任务运行时才应该运行它——这部分工作正常 当我离开页面时,我想取消任务-我似乎无法让那部分工作。当如何取消任务C#,c#,xamarin.forms,async-await,task-parallel-library,cancellation,C#,Xamarin.forms,Async Await,Task Parallel Library,Cancellation,我有一个任务,它从Web服务检索一些数据。只有当我打开一个页面(这是Xamarin.Forms)时,才应该调用Webservice,并且只有在没有其他版本的任务运行时才应该运行它——这部分工作正常 当我离开页面时,我想取消任务-我似乎无法让那部分工作。当OnAppearing(),OnDisappearing(),在Web服务返回数据之前点击OnAppearing(),日志只写“任务已尝试启动…”,这意味着任务没有被取消。相反,当调用OnDisappearing()`时,任务应该被取消 我试着按
OnAppearing()
,OnDisappearing()
,在Web服务返回数据之前点击OnAppearing(),日志只写“任务已尝试启动…”,这意味着任务没有被取消。相反,当调用
OnDisappearing()`时,任务应该被取消
我试着按照StackOverflow上发布的一些示例进行操作,但似乎不起作用,我也不太明白
我的代码如下:
一经出现:
private Task task;
CancellationTokenSource tokenSource = new CancellationTokenSource();
protected override void OnAppearing()
{
base.OnAppearing();
if (task != null && (task.Status == TaskStatus.Running || task.Status == TaskStatus.WaitingToRun || task.Status == TaskStatus.WaitingForActivation))
{
Debug.WriteLine("Task has attempted to start while already running");
}
else
{
Debug.WriteLine("Task has began");
var token = tokenSource.Token;
task = Task.Run(async () =>
{
await GetDataAsync();
/* EDIT: This is what I originally posted, but doesn't work so have commented it out
while (!token.IsCancellationRequested)
{
await GetDataAsync();
}
*/
}, token);
}
}
OnDisappearing:
protected override void OnDisappearing()
{
base.OnDisappearing();
Debug.WriteLine("Page dissapear");
tokenSource.Cancel();
Debug.WriteLine("Task Cancelled");
}
GetData方法
public async Task GetData()
{
WebAPI api = new WebAPI();
try
{
Device.BeginInvokeOnMainThread(() =>
{
PageLoading();
});
string r = await api.GetProfileStatus(token);
Device.BeginInvokeOnMainThread(async () =>
{
if (r == "OK")
{
GetDataSuccess();
}
}
}
catch (Exception e)
{
// log exception
}
}
你在错误的地方做了正确的检查:
var token = tokenSource.Token;
task = Task.Run(async () =>
{
while (!token.IsCancellationRequested)
{
await GetDataAsync();
}
}
在这里开始任务,然后在循环中一次又一次地开始。正确的做法是检查GetData
中的令牌,如果可能,进一步检查api
变量。在这种情况下,您可以根据需要取消服务呼叫
旁注:
- 使您的事件处理程序
,不要将您的工作包装在异步
任务中。运行
- 使您的
GetData
可以实际返回调用代码的状态,然后可以删除任务
,因为BeginInvokeMainThread
将在异步操作后恢复上下文Wait
protected override async void OnAppearing()
{
base.OnAppearing();
if (task != null && (task.Status == TaskStatus.Running || task.Status == TaskStatus.WaitingToRun || task.Status == TaskStatus.WaitingForActivation))
{
Debug.WriteLine("Task has attempted to start while already running");
}
else
{
Debug.WriteLine("Task has began");
var token = tokenSource.Token;
PageLoading();
var r = await GetDataAsync(token);
if (r == "OK")
{
GetDataSuccess();
}
}
}
public async Task GetDataAsync(CancellationToken token)
{
WebAPI api = new WebAPI();
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
try
{
return await api.GetProfileStatus(token);
}
catch (Exception e)
{
// log exception and return error
return "Error";
}
}
GetData从哪里获得令牌?它和上面的一样吗?@Steve下次给你的代码适当的空格,它会让你的代码更容易理解readable@SamiKuhmonen我不确定。我以为传递到“Task.Run(async()=>…”中的令牌就是令牌?真的不太熟悉。@johnny5 OK注意到-谢谢。删除
任务。Run
-这是不必要的,因为GetData(async)已经是异步的,所以不需要在另一个任务中包装它-并提供GetData(async)使用取消令牌。取消的方式和效果取决于GetProfileStatus的实现方式。您好,谢谢!我将试一试,看看效果如何。我不确定OnAppearing是否可以标记为async,因为它是从Xamarin.Forms继承来的。这就是为什么我使用Task.Run。看起来这确实有效,并更改了OnAppearing同样也要感谢async。async
不是方法签名的一部分,而async void
仅适用于事件处理程序:)