我有一个Task,它从Web服务中检索一些数据。只有当我打开一个页面时才会调用Webservice(这是Xamarin.Forms),只有在没有其他版本的任务运行时才能运行它 - 这部分工作正常。
当我离开页面时,我想要取消任务 - 我似乎无法让这件事工作。当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
,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()`被调用时。
我试图按照StackOverflow上发布的一些示例进行操作,但似乎无法正常工作,我无法理解它。
我的代码如下:
OnAppearing:
protected override void OnDisappearing()
{
base.OnDisappearing();
Debug.WriteLine("Page dissapear");
tokenSource.Cancel();
Debug.WriteLine("Task Cancelled");
}
OnDisappearing:
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
}
}
GetData方法
var doc = new HtmlDocument();
doc.Load(file);
var htmlBody = doc.DocumentNode.SelectSingleNode("//body");
var headerTables = doc.DocumentNode.SelectSingleNode("//body/table[1]");
var headerNode = doc.DocumentNode.SelectSingleNode("//h4[contains(text(),'Information Research, Vol')]");
htmlBody.ReplaceChild(headerNode, headerTables);
headerTables.Remove();
doc.Save(file);
答案 0 :(得分:2)
你在错误的地方做正确的检查:
var token = tokenSource.Token;
task = Task.Run(async () =>
{
while (!token.IsCancellationRequested)
{
await GetDataAsync();
}
}
在这里你开始任务,然后在循环中一次又一次地启动它。正确的做法是检查GetData
内的令牌,如果可能的话,检查api
变量。在这种情况下,您可以根据需要取消服务电话。
附注:
async
,不要将您的工作包装在Task.Run
GetData
Task<T>
,以便您可以实际将状态返回到调用代码,然后您可以删除BeginInvokeOnMainThread
,因为await
将在异步操作后恢复上下文< / LI>
所以你的代码将是这样的:
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 GetData(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";
}
}