簡體   English   中英

C#async,在完成一個任務而不訪問代碼時停止所有任務

[英]C# async, Stop all tasks when one is finished without the access to the code

我正在編寫一個在.NET中使用Provider Model模式的小應用程序。 每個提供程序都有一種方法可以實現,以便在我的應用程序中插件。

我想在不同的線程中運行所有提供者的特定工作(實現的方法)但是當一個任務完成時,所有其他任務都需要停止執行。

我在.NET中使用async / await模型和CancellationToken來取消任務。

tasks.Add(Task.Run(() =>
                {
                        if (token.IsCancellationRequested)
                            token.ThrowIfCancellationRequested();

                        return provider.DoWork();

                }, token));

while (tasks.Count > 0)
        {
            var t = await Task.WhenAny(tasks);

            tasks.Remove(t);

            var result = await t;

            if (!string.IsNullOrEmpty(result))
            {
                tokenSource.Cancel();
                return result;
            }
        }

一些provider.DoWork()方法可能非常慢,並且要停止DoWork方法執行的線程,我必須在DoWork方法中檢查token.IsCancellationRequested,但我不能,因為這些方法是從其他人寫的,例如。 在這種情況下,對DoWork外部的token.IsCancellationRequested的檢查並不重要。

總而言之,當一個任務完成時,必須停止其他任務,但不能訪問每個線程中運行的代碼。

期待聽到您的想法。

在一個進程中突然終止一個線程有很多問題 - 基本上,這應該只是作為最后的手段,當進程如此惡心,你無論如何都要殺死整個事件。 除此之外的任何事情,如果你干涉,你將面臨重大問題的嚴重風險。 所以:那將留下優雅的選擇性退出。 你提到你已經在使用取消令牌; 真的,這就是你能做的一切(至少安全)。 由不同的實現來檢查取消和退出。 如果您不能依賴於定期檢查取消的任務:您有點卡住了。

基本上,你所描述的內容並不容易。

有幾種不同的方法可以阻止任意代碼,其中沒有一種是理想的。

首先,您可以在線程級別上進行此操作。 換句話說,為每個提供程序提供一個單獨的線程,並在希望它停止時調用Thread.Abort 不幸的是,這種方法存在無數的問題:兩個更為人熟知的問題是死鎖的可能性,並進入一個奇怪的狀態,其中一個類型不能再在你的AppDomain中實例化。 出於這個原因, Thread.Abort被認為是“邪惡的”和明確的代碼氣味。

向上移動一級,您可以在AppDomain級別上進行此操作。 在這種情況下,您為每個提供程序提供單獨的AppDomain。 這種方法的優點是可以比線程更干凈地關閉AppDomain。 不幸的是,有些事情仍然可以解決問題:特別是,非托管資源可能會從AppDomain泄漏到您的進程中。

這為您提供了最可靠的解決方案:在流程級別上接近此解決方案。 也就是說,您為每個提供程序提供單獨的進程,並使用進程間通信來控制它。 由於操作系統負責清理,因此可以干凈地關閉進程。 不幸的是,這種方法開銷最大,編程最困難。

強大的托管解決方案必須至少支持最后一個。 例如,ASP.NET支持所有這三種:在某些情況下可以中止請求線程(例如,客戶端斷開連接),可以回收AppDomain,並將其升級到整個工作進程被回收的位置。 但是,我建議您不要使用升級策略編寫自己的托管平台。

我建議1)向您的提供商提供CancellationToken並鼓勵他們使用它,2)在您發出令牌信號后,讓它們運行完成。

暫無
暫無

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

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