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

C# 按钮单击事件上的多线程代码使应用程序处于挂起状态,c#,multithreading,c#-4.0,datagridview,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

这是我的代码:

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
        }
    }
}
这是我的表单的外观:

但是,单击按钮1时,应用程序将保持这种状态,并且什么也不做。我的算法很简单——我将datagridview列数从0->n/2和n/2+1->n中划分,然后锁定一组列并解锁其余列


请帮助。

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

t1.Join();
t2.Join();
Join告诉UI线程它应该阻止,直到这些线程完成。当线程完成时,您需要单独的回调/事件来触发,或者,如果您使用的是.NET 4.5,则可以使用任务异步功能,并在后台线程调用中使用wait


查看这篇文章,了解如何使用新的async/await关键字。

是的,您的应用程序已经有了一个。您的工作线程在dgv中等待。调用以使主线程完成,同时,您的主线程在Join中等待工作线程无限期完成,从而导致死锁

在不必要的地方使用线程。我的意思是你的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());
}

@SriramSakthivel-如何和在哪里?他的意思是,如果主线程调用thread.Join来等待后台线程,它不会输出消息并因此响应invoke如何解决此问题?解决此问题的最佳方法是去掉多线程代码;它没有提供任何好处。但我有一个情况,我锁定了很多单元格,这里我以列作为示例。想象一下,如果有55000个单元格我需要根据某种条件执行锁定,那么我该怎么做呢?不管怎样,这完全取决于你在方法内部做了什么。如果你在整个方法中都使用UI,你应该只在主线程中使用它。如果你能发布原始代码,我们可以建议更好的选择。所以基本上你是说我无法在UI上使用多线程代码?@LhtLohit-Nope,请仔细阅读我的评论。如果任何cpu绑定操作或任何IO绑定操作都可以在工作线程中执行。如果你触摸整个UI,方法就是在UI线程中操作。好的,您可以在工作线程中执行,但这不会更好,因为您需要大量的Invoke或BeginInvoke调用。如果不知道原始代码是什么样子,很难回答。你能举一个工作线程的例子吗?我可以解决这个问题,我会接受你的回答。