应用进入后台时任务取消
Posted
技术标签:
【中文标题】应用进入后台时任务取消【英文标题】:Task Cancellation when app enters background 【发布时间】:2016-09-26 08:54:41 【问题描述】:我正在研究 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);
当应用程序进入前台时,我再次调用 getData() 方法,以便重新开始。
发生的情况是,Task 没有被取消,而是 getSomeMoreData 被调用了两次(或应用程序从后台转到前台的次数)。
有人可以解释我如何实现这一目标吗?这里发生了什么?
【问题讨论】:
【参考方案1】:其实这不是 Xamarin 的问题,只是 C# 的问题,除了应用程序的进入前台/后台事件。
对于你需要的需求,你应该做一个任务管理器对象来实现它。
我为你写了一个示例代码:
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.");
希望对你有帮助。
【讨论】:
以上是关于应用进入后台时任务取消的主要内容,如果未能解决你的问题,请参考以下文章