运行 后台工作人员冻结/死亡
Background worker freezes / dies while running
这可能是一个硬件问题,因为我不确定后台工作者是如何实现的,但问题是:我有 3 个后台工作者运行宁不同的线程。我已将这些线程编码为在它们开始和结束时显示,但我得到了一些非常奇怪的结果。
在某些执行中,所有 3 个线程都会启动,但只有 1 个会结束(我已经等了很多分钟,看看程序是否只是执行得很慢,并在代码中打断 - 它不是 运行ning 慢,后台工作者只是 "dies")。其他执行我得到 2 个线程来完成。其他时候我只有 2 个线程开始和结束,等等
我根本没有在 运行 之间更改代码(在下面输入),我只是停止并重新启动程序。因此,我怀疑这可能是硬件问题(CPU 也许吧?)。不幸的是,我现在没有另一台 PC 来测试程序,我正在使用的 PC 是... "far from the best".
所以,我的问题是:是否存在硬件问题导致后台工作程序(及其正在处理的线程)停止运行/根本无法启动?或者它绝对必须是代码中的内容吗?
(以下显然不是我的代码。它是一个更简单的版本来说明问题)代码:
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 run/finish 一些线程,但不是全部(同样,我让程序 运行 几分钟,所以我知道它不仅仅是 运行 慢)...?)
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?
这是非常非常不可能的。
我怀疑真正的问题是您正在从多个主题更新 text
。像这样连接字符串不是线程安全的操作,线程可以预计大约同时完成。即使循环具有不同的迭代次数,线程调度中的微小波动也可能导致它们相互踩踏。特别是,行
text += Environment.NewLine + "Ending thread 1" + Environment.NewLine + "at " + timeKeeper.Elapsed.ToString();
可以 运行 这样
- 线程 1 读取文本的当前值。
- 线程 1 被中断
- 线程 2 被调度并且也读取文本的当前值
- 线程 2 更新文本中的值
- 线程 2 被中断
- 线程 1 已安排。它会覆盖文本,而不会重新读取线程 2 刚刚所做的更改。
尝试使用 lock
语句来更改线程共享的资源。
这可能是一个硬件问题,因为我不确定后台工作者是如何实现的,但问题是:我有 3 个后台工作者运行宁不同的线程。我已将这些线程编码为在它们开始和结束时显示,但我得到了一些非常奇怪的结果。
在某些执行中,所有 3 个线程都会启动,但只有 1 个会结束(我已经等了很多分钟,看看程序是否只是执行得很慢,并在代码中打断 - 它不是 运行ning 慢,后台工作者只是 "dies")。其他执行我得到 2 个线程来完成。其他时候我只有 2 个线程开始和结束,等等
我根本没有在 运行 之间更改代码(在下面输入),我只是停止并重新启动程序。因此,我怀疑这可能是硬件问题(CPU 也许吧?)。不幸的是,我现在没有另一台 PC 来测试程序,我正在使用的 PC 是... "far from the best".
所以,我的问题是:是否存在硬件问题导致后台工作程序(及其正在处理的线程)停止运行/根本无法启动?或者它绝对必须是代码中的内容吗?
(以下显然不是我的代码。它是一个更简单的版本来说明问题)代码:
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 run/finish 一些线程,但不是全部(同样,我让程序 运行 几分钟,所以我知道它不仅仅是 运行 慢)...?)
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?
这是非常非常不可能的。
我怀疑真正的问题是您正在从多个主题更新 text
。像这样连接字符串不是线程安全的操作,线程可以预计大约同时完成。即使循环具有不同的迭代次数,线程调度中的微小波动也可能导致它们相互踩踏。特别是,行
text += Environment.NewLine + "Ending thread 1" + Environment.NewLine + "at " + timeKeeper.Elapsed.ToString();
可以 运行 这样
- 线程 1 读取文本的当前值。
- 线程 1 被中断
- 线程 2 被调度并且也读取文本的当前值
- 线程 2 更新文本中的值
- 线程 2 被中断
- 线程 1 已安排。它会覆盖文本,而不会重新读取线程 2 刚刚所做的更改。
尝试使用 lock
语句来更改线程共享的资源。