2016-10-27 4 views
1

最初にタスクを開始したメソッドから抜けたら、現在実行中のタスクをIDでフェッチする方法はありますか?私は何とか現在のタスクを取得したいので、プログラムの流れを中断することなく途中実行を中止することができます。例えばC#非同期タスクをフェッチする

class Test 
{ 
    List<Task> listOfTasks = new List<Task>(); 


    void taskCaller() 
    { 
     try 
     { 
      var myTask = Task.Factory.StartNew(()=> testMethod()); 
      listOfTasks.Add(myTask); 
     } 
     catch (System.Exception) 
     { 
      //... 
      throw; 
     } 
    } 


    void taskGetter() 
    { 
     foreach (var item in listOfTasks) 
     { 
      if(item == something) 
      { 
       item.KillExecution(); 
      } 
     } 
    } 


    private void testMethod() 
    { 
     // doing something 
     throw new NotImplementedException(); 
    } 
} 

EDIT

私は可能であれば私はそれがしたいと、それは私のために動作しませんように私は、タイマーフェッチを実行していますので、それがキャンセルトークンなしで行わたい私はすぐにtoken.Cancel()とタスクを殺す場合にのみ、私はtoken.CancelAfter()を試してみると、DBからのDLLとキャンセルトークンが動作します。

EDIT2:

コードのトンをコピーするのではなく、ここでは全体の流れの擬似です:plast1kの提案を続けて

new timer(repeat method every xx time units) 
    open DB 
    do some work 
    save DB 

は...

私がチェックした場合このシナリオでキャンセルが要求された場合は、trueと表示されますが、実行中のタスクには何もしません。

private void getActiveTasks() 
{ 
    if (!ListOfTasks.Any()) 
     return; 
    Console.WriteLine("Currently running:"); 
    foreach (var task in ListOfTasks) 
    { 
     Console.WriteLine("\t" + task.Key); 
     Console.WriteLine("\t" + task.Value.MyTask.Id); 
     task.Value.Token.Cancel(); 
     Console.WriteLine("\t" + task.Value.Token.IsCancellationRequested); 


     ListOfTasks.Remove(task.Key); 
     return; 
    } 
} 
+1

ような何かを行うことができますあなたは何か間違ったことをしています。なぜ彼らは働かないのか説明できますか? [XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)を参照してください。 – Equalsk

+0

ここでは、私はそれを更新しました – Norgul

+0

キャンセルトークンを間違って実装しているように聞こえます。これは協調的な取り組みであり、DBからフェッチするメソッドは、渡されたトークンが取り消されたかどうか、そしてメソッドが正常に終了するかどうか定期的にチェックする必要があります。 CancelAfterをCancelよりも前に使用する理由がわかりません。特に、できるだけ早く取り消したい場合はどうすればよいでしょうか? – Equalsk

答えて

2

あなたがすでに調査したことがあるように、タスクをキャンセルする唯一の方法は、cancelationtokenを使用してキャンセルを認識させ、キャンセル対応にすることです。また、それを行うための好ましい方法です。しかし、キャンセルソースを使用できないというあなたの質問には、別のSO回答(リンクを含む)に記載されているテクニックを使用することができます。

リンクから要旨、あなたはこれらのタスクを作成して、別のスレッドでそれらを実行して、あなたが実際にキャンセルを処理していることを確認したタスクに

How do I force a Task to stop?

1

をキャンセルすることもできますいつでもスレッドを中止することがあり(cancelToken.ThrowIfCancellationRequested()経由)トークンソースのキャンセルを呼び出すと、タスクスケジューリングがキャンセルされるだけで、実際には実行が停止することはありません。

タスクを停止する適切な方法は、キャンセルトークンを使用することです。 あなたができたあなたのスレッドやタスクを追跡するために、適切なキャンセル技術のためのusaipavanの答えとリンクを参照してください必要がありますが、ここで

https://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx

、ここ

https://blogs.msdn.microsoft.com/andrewarnottms/2014/03/19/recommended-patterns-for-cancellationtoken/

+0

彼の質問では、彼が実行しようとしているメソッドがキャンセルトークンをサポートしていないようであるので、たとえラッパーメソッドが外部呼び出しをキャンセルできなかったとしても。 – plast1k

1

を例を参照してください。リストの代わりに辞書に追加して、あなたの選択したIDを割り当てます。これは、整数または文字列、またはこの例のGUIDである可能性があります。

Dictionary<Guid, Task> listofTasks = new Dictionary<Guid, Task>(); 

public Guid StartTask() 
{ 
    Task myTask = Task.Factory.StartNew(()=> testMethod()); 
    Guid taskID = Guid.NewGuid(); 
    listOfTasks.Add(taskID, myTask); 
    return taskID; 
} 

public void CancelTask(Guid id) 
{ 
    // listOfTasks[id].choose_your_own_task_cancellation_adventure() 
} 

キャンセルトークンを使用できる場合は、それらを辞書/別の辞書に/タプルとして保存することができます。あなたは(すなわち、「DBクエリ」操作を要求のすべてをキャンセル)これらのタスクのグループを特定したい場合はキャンセルトークンがない場合は、あなたはジャークになろうとしたがないこの

public class TaskWrapper 
{ 
    public TaskWrapper(string operationID, Task task, CancellationTokenSource cancellationSource) 
    { 
     this.OperationID = operationID; 
     this.Task = task; 
     this.CancellationSource = cancellationSource; 
    } 
    public string OperationID { get; set; } 
    public Task Task { get; set; } 
    public CancellationTokenSource CancellationSource { get; set; } 
} 


private Dictionary<Guid, TaskWrapper> ListOfTasks = new Dictionary<Guid, TaskWrapper>(); 


// populate the list 


public void CancelAll(string operation) 
{ 
    listOfTasks.Where(a => a.OperationID == operation).CancellationSource.Cancel(); 
} 
+0

Ideaは素晴らしいですが、私はトークンを使用するようには思えません...私はタイマー(見た目の編集)を使用しているので、特定のタスクに関連するトークンは何とか "オーバーライド"され、私はそれをキャンセルすると...何も起こらない? – Norgul

+0

'MyTask [id] .Token.Cancel()'のようなものがありますか?だから私は直接トークンが転送されているタスクを知っていますか? – Norgul

+0

@Norgul Yes thats possible - 辞書の詳細については、https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspxを参照してください。また、キャンセルトークンを使用して、提供したシナリオを適切にキャンセルできない場合もあります。 – plast1k