[英]Task Cancellation when app enters background
我正在使用xamarin形式PCL + iOS。 我想取消一個進入背景的任務。 並在應用程序進入前台時重新開始。
這是到目前為止我嘗試過的。.我不確定我的方式是否取消任何任務,或者這是什么情況?
async void getData()
{
bool isSuccess = await getSomeData();
if(isSuccess)
await getSomeMoreData();
}
CancellationTokenSource cts;
async Task<bool> getSomeData()
{
cts = new CancellationTokenSource();
AppEntersBackgorund += (sender,args) => { cts. cancel();});
CancellationToken token = new CancellationToken();
token = cts.token;
await Task.Run(() => {
token.ThrowIfCancellationRequested();
isSuccess = ParserData(token); // parsedata also checks periodically if task is cancelled
},token); //what happens here when cancel called?
return isSuccess;
}
async void getSomeMoreData()
{
if(!cts.IsCancellationRequested)
cts = new CancellationTokenSource();
AppEntersBackgorund += (sender,args) => { cts. cancel();});
CancellationToken token = new CancellationToken();
token = cts.token;
await Task.Run(() =>
{
token.ThrowIfCancellationRequested();
ParseSomeMoreData(token);
},token);
}
當應用程序進入foregorund時,我再次調用getData()方法,以便重新開始。
發生的是,任務沒有被取消,而是getSomeMoreData被調用兩次(或應用程序從后台運行到前台的次數)。
有人可以解釋我如何實現這一目標嗎? 在這里發生了什么?
實際上,這不是Xamarin問題,只是C#問題,除了應用程序的enter前/后事件。
為了滿足您的需求,您應該使一個任務管理器對象實現它。
我為您編寫了一個示例代碼:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
namespace BackGroundTask
{
public class TaskManager
{
//The instance property
private static TaskManager instance;
public static TaskManager Instance{
get{
if(null == instance)
instance = new TaskManager();
return instance;
}
}
private bool actionTaskFreeFlag = true;//Flag for if actionTask is available or not
private Queue<Action> taskQueue;//A queue to collect the tasks you added into the manager
private Task scanTask;//A Task to sacn the queue
private Task actionTask;//A task to do the current action
private Thread actionTaskRunningThread;//Record the thread that current action is working on
public TaskManager()
{
taskQueue = new Queue<Action>();
scanTask = new Task(() =>
{
while (true)
{
if (actionTaskFreeFlag && taskQueue.Count > 0)//If there still something to do and the actionTask is available then do the action
{
actionTaskFreeFlag = false;
Action action = taskQueue.Dequeue();
actionTask = new Task(() => {
actionTaskRunningThread = System.Threading.Thread.CurrentThread;
action();
});
actionTask.Start();
actionTask.ContinueWith(delegate {
actionTaskFreeFlag = true;
});
}
}
});
scanTask.Start();
}
public void AddAction(Action action)
{
taskQueue.Enqueue(action);
}
public void CancelCurrentTaskAndClearTaskQueue()
{
Console.WriteLine("CancelCurrentTaskAndClearTaskQueue");
if(null != actionTaskRunningThread)
actionTaskRunningThread.Abort();
taskQueue.Clear();
}
}
}
這是有關如何使用它執行所需工作的示例代碼:
//App enter background event
AppDelegate.Instance.AppDidEnterBackground += delegate {
TaskManager.Instance.CancelCurrentTaskAndClearTaskQueue();
};
//App enter forcenground event
AppDelegate.Instance.AppWillEnterForeground += delegate {
if (AppDelegate.FlagForGetData)
{
TaskManager.Instance.AddAction(GetData);
TaskManager.Instance.AddAction(GetMoreData);
}
};
這是測試方法:
private void GetData()
{
AppDelegate.FlagForGetData = true;
Console.WriteLine("Began getting data.");
System.Threading.Thread.Sleep(5000);
AppDelegate.FlagForGetData = false;
Console.WriteLine("Getting data succeed.");
}
private void GetMoreData()
{
Console.WriteLine("Began getting more data.");
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Getting more data succeed.");
}
希望它能對您有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.