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调用。如果不知道原始代码是什么样子,很难回答。你能举一个工作线程的例子吗?我可以解决这个问题,我会接受你的回答。