2015-10-08 121 views
0

首先,我對多線程和tpl尤其陌生,因此下面的代碼可能很糟糕。真的很差:)從taskschedule中取消任務會取消其中的所有其他任務

所以,我有以下目標: 有任務隊列,任務進行內聯,並且任務「工作」的進度應該在ProgressBar上。

我超載TaskScheduler類:

public class MyTaskScheduler:TaskScheduler 
{ 
    [ThreadStatic] 
    private static bool _currentThreadIsProcessingItems; 

    private static Logger _logger; 

    private readonly TaskQueue _scheduledTasks; 
    private readonly int _maxDegreeOfParallelism; 
    private int _delegatesQueuedOrRunning = 0; 
    public MyTaskScheduler(int maxDegreeOfParallelism) 
    { 
     _logger = LogManager.GetLogger("log"); 
     _maxDegreeOfParallelism = maxDegreeOfParallelism; 
     _scheduledTasks = new TaskQueue(); 
    } 

    public override int MaximumConcurrencyLevel { get { return 1; } } 
    protected override IEnumerable<Task> GetScheduledTasks() 
    { 
     lock (_scheduledTasks) 
     { 
      return _scheduledTasks.ToList(); 
     } 
    } 

    protected override void QueueTask(Task task) 
    { 
     lock (_scheduledTasks) 
     { 
      _scheduledTasks.Enqueue(task); 
      if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism) 
      { 
       ++_delegatesQueuedOrRunning; 
       NotifyThreadPoolOfPendingWork(); 
      } 
     } 
     _logger.Info("Task queued"); 
    } 

    protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) 
    { 
     if (!_currentThreadIsProcessingItems) return false; 
     if (taskWasPreviouslyQueued) 
      if (TryDequeue(task)) 
       return TryExecuteTask(task); 

      else 
       return false; 
     return TryExecuteTask(task); 
    } 

    private void NotifyThreadPoolOfPendingWork() 
    { 

     ThreadPool.UnsafeQueueUserWorkItem(_ => 
     { 
      _currentThreadIsProcessingItems = true; 
      try 
      { 
       while (true) 
       { 
        Task item; 
        lock (_scheduledTasks) 
        { 
         if (_scheduledTasks.Count == 0) 
         { 
          --_delegatesQueuedOrRunning; 
          break; 
         } 
         item = _scheduledTasks.Dequeue(); 
        } 
        _logger.Info("Execution of thread with id {0} started",item.Id); 
        TryExecuteTask(item); 
        _logger.Info("Execution of thread with id {0} ended", item.Id); 
        MessageBox.Show("ggg"); 
       } 
      } 
      finally 
      { 
       _currentThreadIsProcessingItems = false; 
      } 
     } 
      , null); 
    } 

} 

而且有我初始化我隊列的代碼部分:

private readonly List<Task> _tasks = new List<Task>(); 
    readonly CancellationTokenSource _cts = new CancellationTokenSource(); 
    private MyTaskScheduler _scheduler; 

    readonly TaskFactory _factory; 

    private int _currentNumberOfThreads; 

    public Form1(bool isMainForm) 
    { 
     InitializeComponent(); 
     _logger = LogManager.GetLogger("log"); 
     _isMainForm = isMainForm; 
     _currentNumberOfThreads = 0; 
     _scheduler = new MyTaskScheduler(1); 
     _factory = new TaskFactory(_scheduler); 
     if (_isMainForm == false) 
     { 
      _currentNumberOfThreads++; 
      var t = _factory.StartNew(() => DoWork(_cts.Token), _cts.Token); 
      _tasks.Add(t); 
     } 

它完美,直到我嘗試取消當前的任務。

private void button2_Click(object sender, EventArgs e) 
    { 
     _logger.Info("Initialized cancelling of current thread"); 
     _cts.Cancel(); 
     _currentNumberOfThreads--; 
    } 

這抵消不僅當前的任務,但在隊列中的所有任務,我可以從日誌中看到:

01:56:18 Task queued 
01:56:18 Execution of thread with id 1 started 
01:56:18 Thread's DoWork() begun 
01:56:19 Task queued 
01:56:22 Task queued 
01:56:30 Thread {0} DoWork() ended 
01:56:30 Execution of thread with id 1 ended 
01:56:31 Execution of thread with id 2 started 
01:56:31 Thread's DoWork() begun 
01:56:32 Task queued 
01:56:32 Task queued 
01:56:33 Task queued 
01:56:34 Initialized cancelling of current thread 
01:56:34 Execution of thread with id 2 ended 
01:56:35 Execution of thread with id 3 started 
01:56:35 Execution of thread with id 3 ended 
01:56:36 Execution of thread with id 4 started 
01:56:36 Execution of thread with id 4 ended 
01:56:36 Execution of thread with id 5 started 
01:56:36 Execution of thread with id 5 ended 
01:56:37 Execution of thread with id 6 started 
01:56:37 Execution of thread with id 6 ended 

任務取消應該取消目前唯一的任務,並在隊列中的下一個任務應該開始這樣工作,通常。 我真的很困惑,不知道我做錯了什麼。我有一個想法,CancellationTokenSource我曾經取消我的任務,是指整個時間表,而不是具體的任務,但我無法證明自己。所以任何幫助將不勝感激。

P.S.對不起,我的英語不好。

+0

是啊,似乎我使用CancellationToken的單個實例爲我所有的任務,當我試圖取消一個我提出取消所有任務的請求。我對嗎? –

回答

0

其實很簡單:

您正在使用一個單一的取消令牌作爲一個字段。

readonly CancellationTokenSource _cts = new CancellationTokenSource(); 

如果你想取消只有一個單一的任務,你需要創建每個任務一個道理,只有取消一個傳遞到你想中止任務。簡單:)