这是我的代码:
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
时,应用程序会保持这种状态并且不执行任何操作。我的算法很简单 - 我将datagridview列数从0->n/2
和n/2+1->n
分开并锁定一堆列并解锁其余列。
请帮忙。
答案 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());
}