2016-05-25 3 views
0

現在、ある時間間隔でタスクを実行しているアプリケーションがありますが、実行中のタスクを停止して再起動できるようにするために、 UIをクリックします。Task.Runの管理とメソッドの停止/キャンセルと進行状況の取得

現在のところ6つのタスクがありますが、必要なときに簡単にもっと一般的なものにすることができます。私はそれらを制御するためのラッパーを作成できることを望んでいました。メソッドをパラメーターとして渡すことができます。このように

は、私はそれから、ステータスの更新を取得だけでなく、私が欲しい

それを管理することができ、私はタスクがあるようにできるだけ多くの作成オブジェクトを作成する: - メソッドを起動/タスク - メソッド/タスクを停止する - メソッド/タスクを再起動する - 更新するために記録したログ/更新/進捗/エラーからフィードバックを得るリスト

これは良い方法ですか?私は何を達成するために?

public class ManagedTask 
    { 
     public ManagedTask() 
     { 
      CreateNewToken(); 
     } 

     public int Id { get; set; } 
     public string DescriptiveName { get; set; } 
     public Action<CancellationToken> TheVoidToRun { private get; set; } 
     private CancellationTokenSource CTokenSource { get; set; } 
     private CancellationToken CToken { get; set; } 
     private Task TheRunningThing { get; set; } 

     public void StartIt() 
     { 
      if (TheRunningThing == null || TheTaskStatus() == TaskStatus.Canceled || TheTaskStatus() == TaskStatus.RanToCompletion) 
      { 
       CreateNewToken(); 
      } 
      // Start up the Task 
      AddUpdate($"Starting Task at {DateTime.Now}"); 
      TheRunningThing = Task.Run(() => TheVoidToRun?.Invoke(CToken), CToken); 
      AddUpdate($"Started Task at {DateTime.Now}"); 
     } 
     public void EndIt() 
     { 
      AddUpdate($"Cancelling Task at {DateTime.Now}"); 
      CTokenSource.Cancel(); 
      // Do - If in progress try to stop (Cancellation Token) 
      // Do - Stop future repeats 
     } 

     private void CreateNewToken() 
     { 
      CTokenSource = new CancellationTokenSource(); 
      CTokenSource.Token.ThrowIfCancellationRequested(); 
      CToken = CTokenSource.Token; 
     } 

     public TaskStatus TheTaskStatus() => TheRunningThing.Status; 


     internal List<string> Updates { get; set; } 

     private void AddUpdate(string updates) 
     { 
      // Do stuff 
     } 
    } 

だから私は、私は次のようにこのようにに渡したいのですが、様々な方法があります。ここでは

public class AvailableTasks 
{ 
    public async void DoStuffThatIsCancelable(CancellationToken token) 
    { 
     DoTheLongStuffOnRepeat(token); 
    } 
    public async void DoAnotherThingThatIsCancelable(CancellationToken token) 
    { 
     DoTheLongStuffOnRepeat(token); 
    } 

    private async void DoTheLongStuffOnRepeat(CancellationToken token) 
    { 
     // Do stuff 
     for (int i = 0; i < 20; i++) 
     { 
      while (!token.IsCancellationRequested) 
      { 
       try 
       { 
        await Task.Delay(500, token); 
       } 
       catch (TaskCanceledException ex) 
       { 
        Console.WriteLine("Task was cancelled"); 
        continue; 
       } 
       Console.WriteLine($"Task Loop at {(i + 1) * 500}"); 
      } 
     } 
    } 
} 

は、私はそれを呼び出すことを考えていた方法です。でも、上記のすべてで、私は今までRanToCompletionを示すステータス苦しむしかし

private static readonly List<ManagedTask> _managedTasks = new List<ManagedTask>(); 

    public static void SetupManagedTasks() 
    { 
     var at = new AvailableTasks(); 
     var mt1 = new ManagedTask 
     { 
      Id = 1, 
      DescriptiveName = "The cancelable task", 
      TheVoidToRun = at.DoStuffThatIsCancelable, 
     }; 
     _managedTasks.Add(mt1); 

     var mt2 = new ManagedTask 
     { 
      Id = 2, 
      DescriptiveName = "Another cancelable task", 
      TheVoidToRun = at.DoAnotherThingThatIsCancelable, 
     }; 
     _managedTasks.Add(mt2); 

     mt1.StartIt(); 
     mt2.StartIt(); 

     Console.WriteLine($"{mt1.DescriptiveName} status: {mt1.TheTaskStatus()}"); 
     Console.WriteLine($"{mt2.DescriptiveName} status: {mt2.TheTaskStatus()}"); 
    } 

    public static void CancelTask(int id) 
    { 
     var mt = _managedTasks.FirstOrDefault(t => t.Id == id); 

     if (mt != null) 
     { 
      mt.EndIt(); 
      Console.WriteLine($"{mt.DescriptiveName} status: {mt.TheTaskStatus()}"); 
     } 
    } 

    public static void GetTaskStatus(int id) 
    { 
     var mt = _managedTasks.FirstOrDefault(t => t.Id == id); 

     if (mt != null) 
     { 
      Console.WriteLine($"{mt.DescriptiveName} status: {mt.TheTaskStatus()}"); 
     } 
    } 

上記の構造をどのようにして私が望むものにすることができますか?

おかげで、 デビッド

+0

これを無視するのではなく、 'TaskCanceledException'を元に戻すだけで十分かもしれません。 – Dirk

答えて

0

私は今までRanToCompletionを示すステータスに苦しみます。

これは、お客様のメソッドがasync voidを使用しているためです。それらはasync Taskである必要があります。私がasync best practices articleに書いているように、async voidを避けるべきです。

その他注意事項...

スタート方法/タスク

再起動方法/タスク

あなたは、スレッドプールにタスクを起動(または再起動)することができますTask.Runを使用してください。しかし、自然に非同期タスクがある場合は、それらをFunc<Task>として表現し、Func<Task>を起動するだけでそれらを開始することができます。

停止方法/タスク

これを行うための唯一の適切な方法は、あなたが正しく使用しているように見えた、CancellationTokenです。それは私が

私は進行状況の更新のいずれかの種類のIProgress<T>を使用することをお勧めします更新リストに記録し、ログ/アップデート/進捗状況/エラーだから

フィードバックを取得します。

関連する問題