c# - 后台工作人员在运行时卡住/死亡

标签 c# multithreading backgroundworker

这可能是一个硬件问题,因为我不确定后台 worker 是如何实现的,但问题是:我有 3 个后台 worker 运行不同的线程。我对这些线程进行了编码,以便在它们开始和结束时显示,但我得到了一些非常奇怪的结果。

在某些执行中,所有 3 个线程都会启动,但只有 1 个会结束(我已经等了很多分钟,看看程序是否执行得很慢,并在代码中打断 - 它并没有运行缓慢,后台工作人员只是“死了”)。其他执行我得到 2 个线程来完成。其他时候,我只有 2 个线程开始和结束,等等。

我根本没有在运行之间更改代码(在下面输入),我只是停止程序并重新启动它。因此,我怀疑这可能是硬件问题(也许是 CPU?)。不幸的是,我现在没有另一台 PC 来测试该程序,而且我正在使用的 PC ......“远非最佳”。

那么,我的问题是:是否存在硬件问题导致后台工作程序(及其正在处理的线程)停止运行/根本无法启动?或者它绝对必须是代码中的某些内容?

(以下显然不是我的代码。它是一个更简单的版本来说明问题)代码:

public partial class Form1 : Form
{
    BackgroundWorker[] workers = new BackgroundWorker[3];
    Stopwatch timeKeeper = new Stopwatch();
    string text = "";

    public Form1()
    {
        timeKeeper.Start();

        InitializeComponent();

        for (int i = 0; i < 3; i++)
        {
            workers[i] = new BackgroundWorker();
            workers[i].DoWork += new System.ComponentModel.DoWorkEventHandler(this.BWWorker_DoWork);
            workers[i].RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.BWWorker_WorkDone);
            workers[i].RunWorkerAsync(i);
        }
    }

    private void BWWorker_WorkDone(object sender, RunWorkerCompletedEventArgs e)
    {
        this.textBox1.Text = text;
    }

    private void BWWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        switch (e.Argument.ToString())
        {
            case "0":
                startThread1();
                break;

            case "1":
                startThread2();
                break;

            case "2":
                startThread3();
                break;
        }
    }

    void startThread1()
    {
        text += Environment.NewLine + "Starting thread 1" + Environment.NewLine + "at " + timeKeeper.Elapsed.ToString();

        this.textBox1.Text = text;

        for (int i = 0; i < 25000; i++)
        {

        }

        text += Environment.NewLine + "Ending thread 1" + Environment.NewLine + "at " + timeKeeper.Elapsed.ToString();
    }

    void startThread2()
    {
        text += Environment.NewLine + "Starting thread 2" + Environment.NewLine + "at " + timeKeeper.Elapsed.ToString();

        this.textBox1.Text = text;

        for (int i = 0; i < 10000; i++)
        {

        }

        text += Environment.NewLine + "Ending thread 2" + Environment.NewLine + "at " + timeKeeper.Elapsed.ToString();
    }

    void startThread3()
    {
        text += Environment.NewLine + "Starting thread 3" + Environment.NewLine + "at " + timeKeeper.Elapsed.ToString();

        this.textBox1.Text = text;

        for (int i = 0; i < 75000; i++)
        {

        }

        text += Environment.NewLine + "Ending thread 3" + Environment.NewLine + "at " + timeKeeper.Elapsed.ToString();
    }
}

没有代码更改的 3 次背靠背运行的结果如下:(第 3 张图片根据需要运行所有 3 次。前 2 次运行/完成一些线程,但不是全部(同样,我让程序运行几分钟,所以我知道它不仅仅是运行缓慢)...?)

enter image description here

最佳答案

So, my question: Could there be hardware issues that cause a background worker (and the thread that it is working on) to just die off / not start at all? Or does it absolutely have to be something in the code?

那是非常非常不可能的。

我怀疑真正的问题是您正在从多个 thead 更新 text。像这样连接字符串不是线程安全的操作,线程可以预计大约同时完成。即使循环具有不同的迭代次数,线程调度中的微小波动也可能导致它们相互踩踏。特别是这条线

text += Environment.NewLine + "Ending thread 1" + Environment.NewLine + "at " + timeKeeper.Elapsed.ToString();

可以这样运行

  • 线程 1 读取文本的当前值。
  • 线程 1 被中断
  • 线程 2 被调度并读取文本的当前值
  • 线程 2 更新文本中的值
  • 线程 2 被中断
  • 线程 1 已安排。它会覆盖文本,而无需重新读取线程 2 刚刚所做的更改。

尝试使用 lock 语句来改变线程共享的资源。

关于c# - 后台工作人员在运行时卡住/死亡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33426627/

相关文章:

android - 在这种情况下如何避免 IllegalStateException : The content of the adapter has changed but ListView did not receive a notification

python - 关闭一个窗口并在另一个窗口中继续执行?

c++ - 互斥体更改是否会广播到多核系统上的其他内核?

c# - 在 C# 中计算百分比

c# - e.cancel = true 后后台worker不会运行 "RunWorkerCompleted";

c# - JWT token 错误 401 在 .net core 3.1 中未经授权

c# - 如何使用 linq 从嵌套字典中选择所有值?

c# - 使用C#访问网站

c# - 如何调用带有空参数的委托(delegate)?

ruby-on-rails - 使用 Resque/Rails 保存工作结果