[英]How to constantly check if threads are alive
我需要跟踪我创建的所有线程何时完成。 在过去的两天里,我一直在逐例搜索和尝试,但无济于事,我想知道是否可以得到一些帮助。 先感谢您。
我的表单基于用户选中的复选框在按钮单击上运行一系列查询。 这些复选框中的每一个都有其自己的线程,这些线程在单击按钮时创建。 根据复选框选择填充Datagridviews和图形。
这是单击按钮和正在创建的两个线程。 我在查询运行时禁用了表单上的控件,因为我不希望用户在另一个正在处理的同时发送另一个查询请求。
有没有一种方法可以使我不断检查线程是否已完成,然后重新启用表单控件?
public void btn_runGRM_Click(object sender, EventArgs e)
{
this.btn_runGRM.Enabled = false;
this.checkBox_Assgn.Enabled = false;
this.checkBox_Avail.Enabled = false;
this.checkBox_RFI.Enabled = false;
this.checkBox_Census.Enabled = false;
this.ChartDGV.Visible = true;
if (checkBox_Assgn.Checked)
{
AssignmentDGV.DataSource = null;
AssignmentDGV.Rows.Clear();
AssignmentDGV.Refresh();
Assgn_timer = new System.Windows.Forms.Timer();
Assgn_timer.Interval = (1000);
Assgn_timer.Tick += new EventHandler(Assgn_timer_Tick);
Assgn_sw = new System.Diagnostics.Stopwatch();
Assgn_timer.Start();
Assgn_sw.Start();
ThreadStart childref1 = new ThreadStart(CallToChildthread1);
Thread childThread1 = new Thread(childref1);
childThread1.Start();
}
if (checkBox_Census.Checked)
{
CensusDGV.DataSource = null;
CensusDGV.Rows.Clear();
CensusDGV.Refresh();
Census_timer = new System.Windows.Forms.Timer();
Census_timer.Interval = (1000);
Census_timer.Tick += new EventHandler(Census_timer_Tick);
Census_sw = new System.Diagnostics.Stopwatch();
Census_timer.Start();
Census_sw.Start();
ThreadStart childref2 = new ThreadStart(CallToChildthread2);
Thread childThread2 = new Thread(childref2);
childThread2.Start();
}
}
这是子线程之一的一些代码
public void CallToChildthread1()
{
string oradb = "......";
OracleConnection conn = new OracleConnection(oradb); // C#
conn.Open();
OracleParameter parm = new OracleParameter();
parm.OracleDbType = OracleDbType.Varchar2;
if (textBox1.Text == "")
{
parm.Value = ' ';
}
else
{
parm.Value = textBox1.Text;
}
cmd = new OracleCommand();
cmd.Connection = conn;
cmd.Parameters.Add(parm);
cmd.CommandText = "SELECT .......";
}
如果要在线程完成之前阻止执行,请使用
Thread childThread1 = new Thread(childref1);
...
childThread1.Join();
childThread2.Join();
// here i am sure two threads have finished
它将阻止执行直到完成。
有关更多示例,请参见此处 。
使用任务。 它们更易于使用。
private void StartTasksAndWaitForThemToFinish() {
// Generate and start worker tasks
Task[] tasks = new [] {
TaskFactory.StartNew(() => {
// task 1
}),
TaskFactory.StartNew(() => {
// task 2
})
};
// Wait for them to finish
Task.WaitAll(tasks);
// Update UI. You might need to invoke to the UI thread.
...
}
private void SomeButtonClickHandler(object sender, EventArgs e) {
// Start tasks and wait for them to finish
TaskFactory.StartNew(StartTasksAndWaitForThemToFinish);
}
因此,经过大约8个小时的研究,我找到了适合自己的解决方案。
在我最终找到适合我的方法之前,我尝试了大约10种不同的处理方式,这可能会使人感到沮丧。 我本可以在5个小时前找到解决方案,但我没有意识到在执行while循环时,您必须调用Forms.Application.DoEvents();
为了使UI可用。
在弄清楚这一点之后,尝试评估所有线程的状态时仍然出现错误,下面将详细介绍。
创建的方法来处理我的线程启动
public Thread thrd1;
public Thread thrd3;
public void MakeThread1(ThreadStart name)
{
thrd1 = new Thread(name);
thrd1.Start();
}
public void MakeThread3(ThreadStart name)
{
thrd3 = new Thread(name);
thrd3.Start();
}
以下内容与我最初发布的内容略有不同。 我调用该方法,而不是从单击按钮内启动线程。
public void btn_runGRM_Click(object sender, EventArgs e)
{
this.btn_runGRM.Enabled = false;
this.checkBox_Assgn.Enabled = false;
this.checkBox_Avail.Enabled = false;
this.checkBox_RFI.Enabled = false;
this.checkBox_Census.Enabled = false;
this.ChartDGV.Visible = true;
if (checkBox_Assgn.Checked)
{
AssignmentDGV.DataSource = null;
AssignmentDGV.Rows.Clear();
AssignmentDGV.Refresh();
ThreadStart childref1 = new ThreadStart(CallToChildthread1);
Thread mt1 = new Thread(childref1);
MakeThread1(childref1);
}
if (checkBox_Assgn.Checked || checkBox_RFI.Checked)
{
while (chart1.Series.Count > 0) { chart1.Series.RemoveAt(0); }
chart1.Visible = true;
ChartDGV.DataSource = null;
ChartDGV.Rows.Clear();
ChartDGV.Refresh();
ThreadStart childref3 = new ThreadStart(CallToChildthread3);
Thread mt3 = new Thread(childref3);
MakeThread3(childref3);
}
当仍然在按钮内单击时,我现在查看线程是否不为空。 如果是,则抛出错误。 如果不是,我开始我的while循环。
if(thrd1 != null)
{
while (thrd1.IsAlive == true)
try
{
Thread.Sleep(50);
System.Windows.Forms.Application.DoEvents();
}
catch
{
}
}
if (thrd3 != null)
{
while (thrd3.IsAlive == true)
try
{
Thread.Sleep(50);
System.Windows.Forms.Application.DoEvents();
}
catch
{
}
}
this.btn_runGRM.Enabled = true;
this.checkBox_Assgn.Enabled = true;
this.checkBox_Avail.Enabled = true;
this.checkBox_RFI.Enabled = true;
this.checkBox_Census.Enabled = true;
}
我将尝试结合thrd为null和thrd进行动态评估,以查看是否无法简化代码的外观。 也许像...
while((thrd1.IsAlive!=Null && thrd1.Isalive== true) ||
(thrd3.IsAlive!=Null && thrd3.Isalive== true))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.