簡體   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