簡體   English   中英

取消任務而不向 Task 方法提供 CancellationTokenSource

[英]Cancellation of a Task without Providing the Task method with the CancellationTokenSource

我正在嘗試提供一種具有兩種方法的功能,一種稱為 StartTask(action mymethod),另一種稱為 StopTask();

問題是操作必須有權訪問 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 參數,但如果該方法已經采用其他參數怎么辦? 任務的創建將在另一個 class 中,它可能不知道要在 CancellationAction 旁邊傳遞什么參數

如果組件沒有提供取消其中一個正在運行的任務的方法,那么調用者應該不能取消它。 它可能會將應用程序/數據庫/任何內容留在未知的 state 中。

所以基本上較低級別的組件應該為調用者提供一種取消任務的方法(ManualResetEvent、CancelAsync 方法,如 BackgroundWorker 等)。 否則調用者應該等待它完成。

如果較低級別的組件不提供這樣的功能,則大多數情況下被認為是糟糕的設計。

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

BackgroundWorkerThread 會給你一個改變來取消任務,然后響應取消。

我不確定我是否完全理解你的問題,但我會試一試。 似乎您正在嘗試在這里一次解決兩個問題。

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

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

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM