【问题标题】:ERROR : Thread was being aborted in c# Windows application错误:线程在 c# Windows 应用程序中被中止
【发布时间】:2016-09-28 09:14:27
【问题描述】:

当我在一个漫长的过程中使用线程来调用等待表单时出现以下错误。

"一个未处理的异常类型 'System.Threading.ThreadAbortException' 发生在 System.Windows.Forms.dll

附加信息:线程被中止。"

有时我的代码运行良好,但有时会出现此错误。

class ProgressCLS
{
    private static Thread th = new Thread(new ThreadStart(showProgressForm));
    public void startProgress()
    {
        th = new Thread(new ThreadStart(showProgressForm));

        th.Start();
    }

    private static void showProgressForm()
    {              
                Waiting sForm = new Waiting();            
                sForm.ShowDialog();
    }

    public void stopProgress()
    {
            th.Abort();
            th = null;          
    }


}

我在showProgressForm() 方法上收到此错误sform.ShowDialog()

我调用这个类的主程序是这样的:

ProgressCLS PC = new ProgressCLS();
PC.startProgress();
TodayDate = txtDate.SelectedDateTime.ToString("yy-MM-dd");
ClearField();
CalculateMSG();
tabControl1.SelectedIndex = 1;
btnShowFolderLocal.Enabled = true;
btnShowFolderTop.Enabled = true;
btnShowDpsFailed.Enabled = true;
btnShowDpsFailed2.Enabled = true;
btnShowFolderTopic.Enabled = true;
ShowMSGButtonClicked = true;
PC.stopProgress();

有什么想法吗?

【问题讨论】:

  • 那是因为您使用了 Thread.Abort() 并且您有一个未发布的 try/catch-em-all 语句。不要捕获 ThreadAbortException。
  • 您不需要单独的线程来显示进度表。显示带有Show 而不是ShowDialog非模态 表单。如果您想报告另一个任务/线程的进度,请使用Progress<T> 并订阅其事件
  • 其实不要用Thread.Abort。它可能不再是曾经的大坏丑狼,但它仍然是一种非常糟糕的代码味道,有很多方法可以处理这种类型的事情没有 Thread.Abort.

标签: c# multithreading winforms progress


【解决方案1】:
private static Thread th = new Thread(new ThreadStart(showProgressForm));  
public void startProgress()
{
    th = new Thread(new ThreadStart(showProgressForm));
    th.Start();
}

没什么大不了的,但你为什么要实例化你的线程两次?不是很干净。 我认为只有你的 ctor 中的那个是强制性的,因为你在调用 stopProgress() 时设置了 th = null。

不管怎样,看看你的代码,记住线程是异步的,所以:

        ProgressCLS PC = new ProgressCLS();
        PC.startProgress();

它在专用线程中运行您的进度表单(异步,因此您的代码仍在运行)。

    TodayDate = txtDate.SelectedDateTime.ToString("yy-MM-dd");
    ClearField();
    CalculateMSG();
    ...

您在主线程中执行一系列进程(同步地,您的进度表仍在后台运行)。

        PC.stopProgress();

无论您的进度表处于何种状态,它都会中止。正如您可能从 MSDN documentation 中错过的那样,它“在调用它的线程中引发 ThreadAbortException”。因此公平地说,您的代码“有时可以工作”甚至很奇怪,因为如果它到达 th.Abort() 行,它应该会失败。

这里有一些提示:

  • 通常我们在主线程中运行 UI 表单,并在后台处理
  • 对于您当前的设计,如果您的任何进程(ClearField() 和 CalculateMSG())有异步操作,您可能会遇到麻烦。
  • 您很少需要显式中止线程(仅当出现意外错误时)。进度完成后只需关闭表单,垃圾收集器即可完成剩下的工作。

【讨论】:

  • @MajidQafouri 为什么要使用单独的线程?只需拨打Show() 而不是ShowDialog()
  • @Panagiotis Kanavos 当我使用 show() 而不是 showDialog() 时,等待表单没有出现
  • @MajidQafouri 该表单显示为顶级表单,可能位于您当前表单的后面。如果您希望表单显示为另一个表单的子项,则需要将其作为参数提供给Form.Show。 ShowDialog 也是如此。 Windows 窗体的基本概念中的模态与非模态形式
  • @MajidQafouri this duplicate question 展示了如何使用非模态表单以及如何从后台任务更新它
  • 是的,Show 不会在后台线程中工作,正如我所说的,通常你在 UI 线程中运行 Show,并在后台处理。
【解决方案2】:

tnx 全部。 我像这样更改了我的进度类代码:

 //private static Thread th = new Thread(new ThreadStart(showProgressForm));
    private static Thread th;
    public void startProgress()
    {
        th = new Thread(new ThreadStart(showProgressForm));

        th.Start();
    }

成功了

【讨论】:

  • 和我之前一样,
  • public void stopProgress() { th.Abort(); th = 空; }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多