如何取消任务 C#
How to cancel Task C#
我有一个从 Web 服务检索一些数据的任务。 Webservice 应该只在我打开一个页面时被调用(这是 Xamarin.Forms)并且它应该只 运行 如果没有另一个版本的任务 运行ning - 这部分工作正常.
当我离开该页面时,我想取消任务 - 我似乎无法使该部分正常工作。当 OnAppearing()
、OnDisappearing()
、OnAppearing() is hit before the webservice returns the data, logs just write "Task has attempted to start..." which means that the Task didn't get cancelled. Instead the task should have been cancelled when
OnDisappearing()` 被调用时。
我尝试按照 Whosebug 上发布的一些示例进行操作,但似乎没有用,而且我不太明白。
我的代码如下:
出现时间:
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);
}
}
消失时:
protected override void OnDisappearing()
{
base.OnDisappearing();
Debug.WriteLine("Page dissapear");
tokenSource.Cancel();
Debug.WriteLine("Task Cancelled");
}
获取数据方法
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
变量。在这种情况下,您可以根据需要取消服务呼叫。
旁注:
- 制作您的事件处理程序
async
,不要将您的工作包装在 Task.Run
中
- 使你的
GetData
Task<T>
这样你实际上可以 return 调用代码的状态,然后你可以删除 BeginInvokeOnMainThread
,因为 await
将恢复异步操作后的上下文
所以你的代码将是这样的:
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";
}
}
我有一个从 Web 服务检索一些数据的任务。 Webservice 应该只在我打开一个页面时被调用(这是 Xamarin.Forms)并且它应该只 运行 如果没有另一个版本的任务 运行ning - 这部分工作正常.
当我离开该页面时,我想取消任务 - 我似乎无法使该部分正常工作。当 OnAppearing()
、OnDisappearing()
、OnAppearing() is hit before the webservice returns the data, logs just write "Task has attempted to start..." which means that the Task didn't get cancelled. Instead the task should have been cancelled when
OnDisappearing()` 被调用时。
我尝试按照 Whosebug 上发布的一些示例进行操作,但似乎没有用,而且我不太明白。
我的代码如下:
出现时间:
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);
}
}
消失时:
protected override void OnDisappearing()
{
base.OnDisappearing();
Debug.WriteLine("Page dissapear");
tokenSource.Cancel();
Debug.WriteLine("Task Cancelled");
}
获取数据方法
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
变量。在这种情况下,您可以根据需要取消服务呼叫。
旁注:
- 制作您的事件处理程序
async
,不要将您的工作包装在Task.Run
中
- 使你的
GetData
Task<T>
这样你实际上可以 return 调用代码的状态,然后你可以删除BeginInvokeOnMainThread
,因为await
将恢复异步操作后的上下文
所以你的代码将是这样的:
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";
}
}