2012-12-02 29 views
0

我對c#中的並行編程和tpl不熟悉,我正在做以下測試以瞭解任務是如何工作的。每次點擊button1並激活有界方法時,都會開始一個新任務。當我點擊button_2時,所有任務都將退出循環,我將得到所有任務耗時的時間以及任務ID。如何使用tpl分別監視和停止正在運行的任務

那麼有沒有辦法在他們在任務池中工作時監視這些任務,以便我可以阻止他們,如果我希望單獨使用任務ID?

 Boolean stopprogramm = false; 
     private void button1_Click(object sender, EventArgs e) 
     { 

      Task timerTask1 = Task.Factory.StartNew(() => 
       { 
        Stopwatch watch = new Stopwatch(); 
        watch.Start(); 
        while (stopprogramm == false) 
        { 
         //Do some work 
        } 
        Console.WriteLine("time ellapsed for No partitioning at all version {0}ms , thread id was {1}", watch.ElapsedMilliseconds, Task.CurrentId); 
        watch.Stop(); 

       }); 


     } 
     private void button2_Click(object sender, EventArgs e) 
     { 
      stopprogramm = true; 
     } 

回答

1

你提到的意思是跟蹤任務和擊球時獲得目標任務按鈕我的其他答案的評論之一鏈接,它看起來像鏈接描述如何使它可以取消。我已經適應我的例子來支持這一點:

private Dictionary<Guid, TaskTracker> _taskMap = new Dictionary<Guid, TaskTracker>(); 

    private void OnButton1Click(object sender, EventArgs eventArgs) 
    { 
     TaskTracker taskTracker = new TaskTracker(Guid.NewGuid(), OnDoWork); 
     _taskMap.Add(taskTracker.Identity, taskTracker); 
     taskTracker.Start(); 
    } 

    private void OnDoWork(CancellationToken token) 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      Thread.Sleep(100); // Do some work, checking if cancel requested every once in a while 
      if (token.IsCancellationRequested) 
      { 
       token.ThrowIfCancellationRequested(); 
      } 
     } 
    } 

    private void OnButton2Click(object sender, EventArgs eventArgs) 
    { 
     Guid identity = _taskMap.Count > 0 ? _taskMap.First().Value.Identity : default(Guid); // find some way to get the desired task 

     TaskTracker taskTracker; 
     if (_taskMap.TryGetValue(identity, out taskTracker)) 
     { 
      taskTracker.TaskExiting += OnTaskExiting; 
      taskTracker.Stop(); 
     } 
    } 

    private void OnTaskExiting(object sender, EventArgs eventArgs) 
    { 
     TaskTracker taskTracker = (TaskTracker)sender; 
     taskTracker.TaskExiting -= OnTaskExiting; 
     _taskMap.Remove(taskTracker.Identity); 

     Console.WriteLine("Time ellapsed for No partitioning at all version {0}ms , thread id was {1}", taskTracker.Stopwatch.ElapsedMilliseconds, Task.CurrentId); 
    } 

    private void OnButton3Click(object sender, EventArgs eventArgs) 
    { 
     Guid identity = _taskMap.Count > 0 ? _taskMap.First().Value.Identity : default(Guid); // find some way to get the desired task 

     TaskTracker taskTracker; 
     if (_taskMap.TryGetValue(identity, out taskTracker)) 
     { 
      taskTracker.TaskExiting += OnTaskExiting; 
      taskTracker.Cancel(); 
     } 
    } 

這裏是向TaskTracker類:​​

public class TaskTracker 
{ 
    private readonly Action<CancellationToken> OnDoWork; 
    private readonly CancellationTokenSource TokenSource; 
    private readonly CancellationToken Token; 

    private bool _isRunning; 
    private Task _task; 

    public TaskTracker(Guid identity, Action<CancellationToken> onDoWork) 
    { 
     TokenSource = new CancellationTokenSource(); 
     Token = TokenSource.Token; 

     Identity = identity; 
     OnDoWork = onDoWork; 
    } 

    public readonly Guid Identity; 
    public readonly Stopwatch Stopwatch = new Stopwatch(); 

    public event EventHandler TaskExiting; 

    public void Start() 
    { 
     _isRunning = true; 
     _task = Task.Factory.StartNew(
      () => 
       { 
        Stopwatch.Start(); 
        try 
        { 
         while (_isRunning) 
         { 
          OnDoWork(Token); 
         } 
        } 
        finally 
        { 
         Stopwatch.Stop(); 

         if (TaskExiting != null) 
         { 
          TaskExiting(this, EventArgs.Empty); 
         } 
        } 
       }, Token 
      ); 
    } 

    public void Stop(bool waitForTaskToExit = false) 
    { 
     if (_task == null) 
     { 
      throw new InvalidOperationException("Task hasn't been started yet"); 
     } 

     _isRunning = false; 
     if (waitForTaskToExit) 
     { 
      _task.Wait(); 
     } 
     _task = null; 
    } 

    public void Cancel() 
    { 
     if (_task == null) 
     { 
      throw new InvalidOperationException("Task hasn't been started yet"); 
     } 

     _isRunning = false; 
     TokenSource.Cancel(); 
     _task = null; 
    } 
} 

基本上,你的「工人」,你會檢查是否令牌表示它被取消,如果是的話,做一些清理工作,然後調用ThrowIfCancellationRequested on token來爆發。

+0

謝謝@taylorjonl它就像一個魅力 – themis

+0

有一點要提的是,即使任務停止,監控現在是可行的,在OnDoWork不會得到令牌,以阻止實際工作的工作。我會試圖弄明白,因爲任務沒有運行,正如我從觀察者那裏看到的那樣。如果我找不到它,我會發佈一個新問題,因爲這是一個新問題。再次感謝你 – themis

1

像這樣的東西可以工作。

private Dictionary<Guid, TaskTracker> _taskMap = new Dictionary<Guid, TaskTracker>(); 

    private void OnButton1Click(object sender, EventArgs eventArgs) 
    { 
     TaskTracker taskTracker = new TaskTracker(Guid.NewGuid(), OnDoWork); 
     _taskMap.Add(taskTracker.Identity, taskTracker); 
     taskTracker.Run(); 
    } 

    private void OnDoWork() 
    { 
     // Do some work 
    } 

    private void OnButton2Click(object sender, EventArgs eventArgs) 
    { 
     Guid identity = _taskMap.Count > 0 ? _taskMap.First().Value.Identity : default(Guid); // find some way to get the desired task 

     TaskTracker taskTracker; 
     if (_taskMap.TryGetValue(identity, out taskTracker)) 
     { 
      taskTracker.TaskExiting += OnTaskExiting; 
      taskTracker.Stop(); 
     } 
    } 

    private void OnTaskExiting(object sender, EventArgs eventArgs) 
    { 
     TaskTracker taskTracker = (TaskTracker)sender; 
     taskTracker.TaskExiting -= OnTaskExiting; 
     _taskMap.Remove(taskTracker.Identity); 
     // do what you want with the timings 
    } 

任務的類是這樣的:

public class TaskTracker 
{ 
    private readonly Action OnDoWork; 
    private Task _task; 
    private bool _isRunning = true; 

    public TaskTracker(Guid identity, Action onDoWork) 
    { 
     Identity = identity; 
     OnDoWork = onDoWork; 
    } 

    public readonly Guid Identity; 
    public readonly Stopwatch Stopwatch = new Stopwatch(); 

    public event EventHandler TaskExiting; 

    public void Run() 
    { 
     Task _task = Task.Factory.StartNew(
      () => 
       { 
        Stopwatch.Start(); 
        try 
        { 
         while (_isRunning) 
         { 
          OnDoWork(); 
         } 
         if (TaskExiting != null) 
         { 
          TaskExiting(this, EventArgs.Empty); 
         } 
        } 
        finally 
        { 
         Stopwatch.Stop(); 
        } 
       } 
      ); 
    } 

    public void Stop() 
    { 
     _isRunning = false; 
     // wait for task to exit? 
     _task = null; 
    } 
} 

您將需要填補空白,2

+0

看起來整潔,但.NET 4.0早已是因爲第三方物流保留任務的關鍵字?,但我在看字典taskmap並觸發我的思想採用類似的東西來監視我的正在運行的任務。但無論如何我會進行測試,謝謝 – themis

+1

我從未使用過這門課。我修改了我的答案,也許更多的是你正在尋找的東西。 TaskTracker類包裝Task對象並管理時間跟蹤。 – taylorjonl

+0

好了,班級工作,該字典確實幫助我監視我的活動任務。只有一個問題仍然存在,如何停止n個任務之一。停止方法似乎沒有停止任何任務 – themis

相關問題