简体   繁体   English

如何不断检查线程是否还活着

[英]How to constantly check if threads are alive

I am in need to track when all threads I have created have finished. 我需要跟踪我创建的所有线程何时完成。 I have searched and tried example after example over the past two days to no avail and was wondering if I could get some assistance. 在过去的两天里,我一直在逐例搜索和尝试,但无济于事,我想知道是否可以得到一些帮助。 Thank you in advance. 先感谢您。

My form runs a series of queries on button click based off of what check boxes the user checks. 我的表单基于用户选中的复选框在按钮单击上运行一系列查询。 Each of these check boxes has it's own thread that gets created on the button click. 这些复选框中的每一个都有其自己的线程,这些线程在单击按钮时创建。 Datagridviews and graphs are populated based on the checkbox selections. 根据复选框选择填充Datagridviews和图形。

Here's the button click and two of the threads being created. 这是单击按钮和正在创建的两个线程。 I disabled the controls on the form while the queries run because I didn't want the user to be able to send another query request while the other was processing. 我在查询运行时禁用了表单上的控件,因为我不希望用户在另一个正在处理的同时发送另一个查询请求。

Is there a method I could make that would constantly check that my threads have completed and would then re-enable my form controls? 有没有一种方法可以使我不断检查线程是否已完成,然后重新启用表单控件?

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();
    }
}

Here is a bit of code from one of the child threads 这是子线程之一的一些代码

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 .......";
}

If you want to block execution until your threads have finished, use 如果要在线程完成之前阻止执行,请使用

Thread childThread1 = new Thread(childref1);
...
childThread1.Join();
childThread2.Join();

// here i am sure two threads have finished

it will block execution until it finished. 它将阻止执行直到完成。

see here for more example. 有关更多示例,请参见此处

Use Tasks. 使用任务。 They are easier to work with. 它们更易于使用。

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);
}

So after about 8 hours more research today, I have a solution that works for me. 因此,经过大约8个小时的研究,我找到了适合自己的解决方案。

It might be botched looking as I played around with about 10 different ways of doing things before i finally got things working for me. 在我最终找到适合我的方法之前,我尝试了大约10种不同的处理方式,这可能会使人感到沮丧。 I could have had a solution 5 hours ago but I didn't realize that when doing a while loop, you have to call the Forms.Application.DoEvents(); 我本可以在5个小时前找到解决方案,但我没有意识到在执行while循环时,您必须调用Forms.Application.DoEvents(); in order for the UI to be usable. 为了使UI可用。

After I figured that out, i was still receiving errors when trying to assess the state of all threads which I will detail below. 在弄清楚这一点之后,尝试评估所有线程的状态时仍然出现错误,下面将详细介绍。

Created Methods to handle my thread starts 创建的方法来处理我的线程启动

    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();

    }

The below only differs slightly from what I originally posted. 以下内容与我最初发布的内容略有不同。 I call the method instead of starting the thread from within the button click. 我调用该方法,而不是从单击按钮内启动线程。

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 still inside the button click, I now look to see if the thread is not null. 当仍然在按钮内单击时,我现在查看线程是否不为空。 It throws an error if it is. 如果是,则抛出错误。 If it isn't, I start my while loop. 如果不是,我开始我的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;


    }

I am going to try and combine the thrd is null and thrd is alive evaluations to see if I cant simplify the look of the code. 我将尝试结合thrd为null和thrd进行动态评估,以查看是否无法简化代码的外观。 maybe something like... 也许像...

while((thrd1.IsAlive!=Null && thrd1.Isalive== true) || 
      (thrd3.IsAlive!=Null && thrd3.Isalive== true))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM