2016-04-22 180 views
0

我想在我的WPF应用程序中实现装载器。在一些繁重的操作中,UI线程被冻结,所以我必须使用线程来实现加载器。每次加载器加载时,都会创建一个新线程,并且在加载器启动时该线程会中止(手动)。我面临的问题是,有时应用程序崩溃给出ThreadAbortExceptionWPF中的线程异常终止

这是启动加载器代码:

try 
     { 
      //if(newWindowThread !=null && !newWindowThread.IsAlive) { } 
      newWindowThread = new Thread(new ThreadStart(() => 
      { 
       try 
       { 
        // Create and show the Window 
        awq = new BusyIndicatorDisguise(BusyMessage); 
        awq.Show(); // <== POINT WHERE THE EXCEPTION IS THROWN 
        //Start the Dispatcher Processing 
        if (!isDispatcherStarted) 
        { 
         var a = Thread.CurrentThread; 
         var b = Dispatcher.CurrentDispatcher; 
         //isDispatcherStarted = true; 
         Dispatcher.Run(); 
        } 

       } 
       catch (ThreadAbortException thEx) 
       { 

       } 
       catch (Exception ex) 
       { 

       } 
      } 
      )); 
      // Set the apartment state 
      newWindowThread.SetApartmentState(ApartmentState.STA); 
      // Make the thread a background thread 
      newWindowThread.IsBackground = true; 
      // Start the thread 
      newWindowThread.Start(); 
     } 
     catch (Exception ex) 
     { 

     } 

此代码是用于停止装载机:

if (newWindowThread != null && newWindowThread.IsAlive) 
     {   
      newWindowThread.Abort();    
     } 

我不能够赶上这个例外在我的catch块。也许是因为它在不同的线程上。 我想知道如何避免ThreadAbortException

+0

考虑使用CancellationToken而不是中止线程。 – yaakov

回答

1

您应该在线程中添加一个try catch块,以便根据您的需要抛出异常并对其进行管理。

无论如何,@Josh在其他类似的帖子说

有中止线程不使用Thread.Abort的不仅混乱在 不可预测的点打断你的代码 的更好的方法,这也是不保证工作,因为如果 您的线程当前正在调用某些非托管代码,则 线程将不会中止,直到控制返回到托管代码。

使用某种类型的同步原语(如 aManualResetEvent)充当标志,告诉您的线程何时退出,这会更好。 您甚至可以为此使用布尔型字段,这是BackgroundWorker所做的。

+0

我已经在我的线程中放了一个try catch块。无论如何,我之前没有听说过** ManualResetEvent **。将试一试,并会让你知道。 –

1

如果您为自己抛出异常,则忘记Thread.Abort。这就是为什么:

  • 抛出异常是一个非常昂贵的操作。它可以保存整个调用堆栈和其他有用的数据以进行调试。在这种情况下,你只需要设置一个简单的标志。
  • ThreadAbortException是一个棘手的问题。除非您在catch块中调用Thread.ResetAbort,否则它会自动重新抛出异常处理程序块的末尾。但不是这样做
  • A ThreadAbortException是一个异步异常,这意味着它可以发生在您的代码的任何一点,这可能会导致不可预知的结果。这是一个蛮力工具,例如任务管理器中的结束任务按钮。只有当您不能重写已执行的代码(第三方组件)并且您确定可以卸载不稳定执行环境的剩余部分(它在AppDomain中执行)时才使用它。

取而代之,请向您的加载程序发送取消请求(可以是简单的bool),您应该在加载操作期间定期轮询。 Here是一个示例,您可以通过使用BackgroundWorker和易失性字段来完成此操作。