2011-06-01 81 views
0

我試圖提供兩個方法之一稱爲StartTask(action mymethod) 和另一個稱爲StopTask()的功能;取消沒有提供任務方法的任務與CancellationTokenSource

問題是操作必須有權訪問CancellationTokenSource以檢查取消並退出方法(返回),這實際上並不是我想要的方法可能在另一個組件或層中,我無法推送每個方法訪問該取消資源,

我不能推動具有處理方法的組件的設計者/開發人員檢查取消和返回。

有沒有什麼辦法可以有這樣的事情,我知道這聽起來很奇怪,不適用,只是想問問。

這是我得到的最好:

 CancellationTokenSource cancellationTokenSource; 
    private void button1_Click(object sender, EventArgs e) 
    { 
     cancellationTokenSource = new CancellationTokenSource(); 
     Task t = new Task(() => Dowork(CancellationAction), cancellationTokenSource.Token, TaskCreationOptions.LongRunning); 
     t.Start(); 
    } 
    private bool CancellationAction() 
    { 

     if (cancellationTokenSource.IsCancellationRequested) 
     { 
      label1.Invoke(new MethodInvoker(() => 
               { 
                label1.Text = "Cancellation Requested!"; 
               })); 
      return true; 
     } 
     return false; 
    } 
    private void Dowork(Func<bool> Return) 
    { 
     int x = 1; 
     while (true) 
     { 
      x++; 
      label1.Invoke(new MethodInvoker(() => 
               { 
                label1.Text = x.ToString(); 
               })); 
      Thread.Sleep(1000); 
      if (Return()) 
      { 
       return; 
      } 
     } 
    } 

問題,這是現在的DoWork必須有一個參數是FUNC,但如果該方法已經採取其他的參數是什麼?創建任務將在另一個類中,可能不知道在旁邊傳遞哪些參數取消操作

+0

由於'CancellationTokenSource'暗示的名稱,它意味着'CancellationToken'的* Source *,獲得了我訪問'Token'屬性的權限。通常,模式是將'CancellationToken'傳遞給依賴任務。這就是說,我無法弄清楚你最終的代碼示例是要達到什麼目的。 – 2011-06-01 13:32:29

回答

0

我不確定我完全理解你的問題,但我會採取一個措施。看起來你正試圖在這裏一次解決兩個問題。

首先,您正在嘗試將參數傳遞給異步線程和/或取消該線程(非常類似的問題)。正如其他人所說BackgroundWorker已經處理取消。該實現類似於將任何參數傳遞給您的線程。如果我正在複製那個功能,例如我會將一個Cancel屬性或方法添加到我的工作線程中,任何其他組件都可以調用並在我的主線程循環中檢查後備值。現在沒有理由取消線程,只是向工作線程傳遞和使用值的示例。

看起來你需要解決的另一個問題是如何在應用程序的不同部分之間發送消息,否則這些消息不需要相互引用。通常我已經看到這種方式是通過某種服務提供商完成的。在上下文或公共模型上實現一個接口,以便所有組件都可以接收實例或可以輕鬆訪問。界面應該包含任何事件,方法和屬性,以便不同的組件可以進行通信。

例如(可能是一個壞例子,但...)如果在文檔關閉時我的語法檢查例程應該取消,我會在IDocumentService接口上定義一個DocumentClosing事件和OnDocumentClosing方法,並在適當的上下文/模型中實現該接口。在創建我的文檔查看器UI組件和語法檢查器線程組件時,我將注入作爲界面鍵入的上下文/模型的實例。當文檔查看器開始關閉文檔時,它會從界面調用OnDocumentClosing方法。創建線程時,它將附加到DocumentClosing事件,並且如果事件觸發,則設置標誌。然後每隔一段時間檢查語法,我會檢查標誌並酌情取消。

這種實現方式使您可以靈活地讓任何組件觸發適當的事件和任何其他組件對他們作出反應,而不管應用程序中組件的使用位置。實際上,即使在同步情況下,這種方法也很有用,例如菜單項目響應應用程序事件而改變狀態。它可以輕鬆對所有組件進行單元測試。責任分離意味着您可以根據需要輕鬆更改任何觸發點和響應。

2

如果組件未提供取消某個正在運行的任務的方法,則調用方應該無法取消它。它可能會讓應用程序/數據庫/任何東西處於未知狀態。

所以基本上,下層組件應該爲調用者提供一種取消任務的方法(ManualResetEvent,CancelAsync方法,如BackgroundWorker等)。否則,主叫方應該等待它結束。

如果較低級別的組件沒有提供這樣的功能,那麼大多數時間被認爲是糟糕的設計。

0

爲什麼不使用BackgroundWorkerThread或其他線程機制? 使用任務並行庫有特別的原因嗎?

BackgroundWorkerThread會給你一個改變,取消任務,然後回覆取消。

+0

使用並行計算有很多優點。 – Stacker 2011-06-01 13:31:57

+1

甚至在這裏列出的優點太多了...檢查出來。這就像從撥號調制解調器到寬帶一樣。一旦你這樣做,你永遠不會回去。 – BonanzaDriver 2011-06-02 06:15:32