簡體   English   中英

按鈕單擊事件上的多線程代碼使應用程序處於掛起狀態

[英]Multithreading code on button click event leaves the application in a hung state

這是我的代碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MteWindowsForm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            dgv.AutoGenerateColumns = false;
            AddCols();
            AddRows();

        }

        void AddRows()
        {
            dgv.Rows.Add(10000);
            bool istrue = true;
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10000; j++)
                {
                    if (istrue)
                    {
                        dgv.Rows[j].Cells[i].Value = "SomeText";
                        istrue = !istrue;
                    }
                    else istrue = !istrue;
                }
            }
        }
        void AddCols()
        {
            for (int i = 0; i < 10; i++)
            {
                DataGridViewColumn dgvCol = new DataGridViewTextBoxColumn();
                string strText = "Column_" + i;
                dgvCol.Name = strText;
                dgvCol.HeaderText = strText;
                dgvCol.FillWeight = 1;
                dgv.Columns.Add(dgvCol);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {

            //lock empty cells
        }
    }
}

這是我的表格:

在此處輸入圖片說明

但是,在單擊Button1 ,應用程序將保持Button1 ,並且不執行任何操作。 我的算法很簡單-我將datagridview列的計數從0->n/2n/2+1->n划分,並鎖定一堆列並解鎖其余列。

請幫忙。

注釋中提到了潛在的死鎖,雖然我不確定是否是這種情況,但應用程序的掛起是由以下幾行引起的

t1.Join();
t2.Join();

Join告訴UI線程應該阻塞直到這些線程完成。 您可能需要一個單獨的回調/事件來在線程完成時觸發,或者,如果您使用的是.NET 4.5,則可以使用任務異步功能並在后台線程調用中使用await

查看有關如何使用新的async / await關鍵字的示例

是的,您的應用程序出現了死鎖 您的工作線程在dgv.Invoke等待。 dgv.Invoke主線程完成,與此同時,您的主線程在Join等待工人無限期完成,從而導致死鎖。

您在不必要的地方使用Thread 我的意思是您的LockCols方法完全可以處理UI因此您必須在UI中運行它。 通過在其他線程中運行循環,您將不會獲得任何好處。 以下代碼是您的更好的版本。

void LockCols(int istart, int iend, bool isReadOnly)
{
    for (int idx = istart; idx < iend; idx++)
    {
        if (isReadOnly)
        {
             dgv.Columns[idx].ReadOnly = isReadOnly;
             dgv.Columns[idx].HeaderText = dgv.Columns[idx].Name + "_" + "ReadOnly";

        }
        else
        {
             dgv.Columns[idx].ReadOnly = isReadOnly;
             dgv.Columns[idx].HeaderText = dgv.Columns[idx].Name + "_" + "Not_ReadOnly";
        }
    }
}

private void button1_Click(object sender, EventArgs e)
{
    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
    sw.Start();
    LockCols(0, dgv.Columns.Count / 2, true);
    LockCols(dgv.Columns.Count / 2 + 1, dgv.Columns.Count, false);
    sw.Stop();
    MessageBox.Show(sw.Elapsed.ToString());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM