2016-09-26 9 views
0

私は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は2回呼び出されます(または、アプリケーションがバックグラウンドからフォアグラウンドに移動する回数)。

私はこれをどのように達成できるのか誰かが説明できますか?そして、ここで何が起こっていますか?

答えて

0

実際には、これは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."); 
} 

希望します。

関連する問題