繁体   English   中英

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

[英]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.

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