簡體   English   中英

終止線程的最佳方法

[英]Best way to terminate a thread

我正在開發一個同時下載多個文件的下載器。 每次下載都有自己的表格,該表格在一個線程中運行下載代碼。 我正在尋找終止正在運行的下載線程的最佳方法,這有兩個原因

  • 用戶取消了下載
  • 主要形式是封閉的

到目前為止,有三種方法

  1. 使用檢查變量,如bool terminate
  2. 使用Thread.Abort()
  3. 運行線程是一個AppDomain並卸載該AppDomain以終止

第一種方法的問題是線程一直運行直到遇到if語句。 即使MainForm已關閉,該過程MainForm繼續運行,直到所有下載線程終止。

我對Thread.Abort不太了解,但強烈建議不要這樣做。

這是最后一種方法的代碼:

public class Processor : MarshalByRefObject
{
    private AsyncOperation _operation;

    private AppDomain Domain { get; set; }

    public delegate void ProgressChangedEventHnadler(Processor sender, int progress);

    public delegate void ProcessedEventHandler(Processor sender, EventArgs e);

    public delegate void ExceptionOccuredEventHandler(Processor sender, Exception ex);

    public event ProgressChangedEventHnadler ProgressChanged;

    public event ProcessedEventHandler Processed;

    public event ExceptionOccuredEventHandler ExceptionOccured;

    private void OnProgressChanged(int progress)
    {
        if(ProgressChanged!=null)
            ProgressChanged.Invoke(this,progress);
    }

    private void OnProcessed(EventArgs e)
    {
        if (Processed != null)
            Processed.Invoke(this, e);
    }

    private void OnExceptionOccured(Exception ex)
    {
        if (ExceptionOccured != null)
            ExceptionOccured.Invoke(this,ex);
    }

    public Processor()
    {
        _operation = AsyncOperationManager.CreateOperation(null);
    }

    public static Processor CreateInstance()
    {
        var locaion = Assembly.GetEntryAssembly().Location;
        var domain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
        var instance =(Processor)domain.CreateInstanceFromAndUnwrap(locaion, typeof (Processor).FullName);
        instance.Domain = domain;
        return instance;
    }

    public void Start()
    {
        var mainThread = new Thread(Process);
        mainThread.Start();
    }

    public void Stop()
    {
        AppDomain.Unload(Domain);
    }

    private void Process()
    {
        //Do the Work and raise events like 
        //_operation.Post(e => OnProcessed((EventArgs)e), EventArgs.Empty);
    }
}

通常,您有兩種選擇:

  • 允許線程終止自身。 這涵蓋了您的第一選擇。

  • 從外部終止線程。 這涵蓋了您的其他選擇。

就是這樣。 而他們沒有,一般來說,可以防止線程無限期的時間后,他們應該 (從視程序員的意圖點)終止運行。

可預測的方法是第一個。 如果終止時間太長,請嘗試以較小的步驟進行處理,以允許更頻繁地檢查終止標志。 另外,請注意IsBackground標志,這將有助於應用程序無法自行關閉。

其他選項的整個問題在於, 任何代碼(除了某些特殊情況,如finally塊除外)都可以在其執行過程中被中斷,這可能導致某些不良結果(例如,某些未托管的資源未釋放),因為在Thread.Abort文檔中進行了解釋。

請注意,最新版本的.NET Framework中的第三種方法等效於在執行線程上調用Abort方法,如文檔所述

域中的線程使用Abort方法終止,該方法將在線程中引發ThreadAbortException 盡管線程應立即終止,但它可以在finally子句中繼續執行不可預測的時間。

因此,從這兩個中使用Thread.Abort似乎更好,因為它更簡單易讀。

如果第一種方法有問題,並且您很清楚線程正在執行的操作類型,並且在兩者之間中斷它們也沒有問題,則“粗略”的方法應該可以。

暫無
暫無

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

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