终止线程的最佳方法

时间:2014-07-29 22:01:47

标签: c# multithreading

我正在使用同时下载多个文件的下载程序。每个下载都有自己的Form,它在一个线程中运行下载代码。我出于两个原因寻找终止正在运行的下载线程的最佳方法

  • 用户取消下载
  • 主窗体已关闭

到目前为止,有三种方法

  1. 使用bool terminate
  2. 等检查变量
  3. 使用Thread.Abort()
  4. 运行该帖子为AppDomain并卸载AppDomain以终止
  5. 第一种方法的问题是线程一直运行直到它到达if语句。即使关闭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);
        }
    }
    

1 个答案:

答案 0 :(得分:2)

一般来说,您有两种选择:

  • 允许线程自行终止。这涵盖了您的第一个选择。

  • 从外部终止线程。这涵盖了您的其他选择。

就是这样。一般来说,在 (从程序员的意图的角度来看)终止后,它们都不会阻止线程无限期地运行。

可预测的方法是第一个。如果终止时间过长,请尝试以较小的步骤进行处理,以便更频繁地检查终止标志。另外,请注意IsBackground标志,这将有助于应用程序无法自行关闭。

其他选项的整个问题是任何代码(除了一些特殊情况,如finally块)可能会在执行过程中被中断,这可能导致一些不受欢迎的结果(例如一些未发布的非托管资源) - 正如Thread.Abort文档中所述。

请注意,最新版本的.NET框架中的第三种方法等同于在执行线程上调用Abort方法,如the documentation中所述:

  

域中的线程使用Abort方法终止,该方法在线程中抛出ThreadAbortException。虽然线程应该立即终止,但它可以在finally子句中继续执行不可预测的时间。

所以从这两个中使用Thread.Abort似乎更好,因为它更简单,更易读。

如果第一种方法有问题,并且如果你很清楚线程正在执行的操作类型,并且中断它们之间没有问题,那么“野蛮”方法应该没问题。