按钮单击事件上的多线程代码使应用程序处于挂起状态

时间:2014-05-11 11:41:05

标签: c# multithreading c#-4.0 datagridview

这是我的代码:

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

这就是我的表格:

enter image description here

然而,在点击Button1时,应用程序会保持这种状态并且不执行任何操作。我的算法很简单 - 我将datagridview列数从0->n/2n/2+1->n分开并锁定一堆列并解锁其余列。

请帮忙。

2 个答案:

答案 0 :(得分:0)

评论中提到了潜在的死锁,虽然我不确定是否是这种情况,但应用程序的挂起是由行引起的

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

Join告诉UI线程它应该阻塞,直到这些线程完成。线程完成时需要单独的回调/事件,或者,如果您使用的是.NET 4.5,则可以使用任务异步功能并在后台线程调用上使用await

请查看此example,了解如何使用新的async / await关键字。

答案 1 :(得分:0)

是的,您的应用已获得Deadlock。您的工作线程在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());
}