我正在尝试显示 datagridview,然后动态填充行。如果我在 UI 线程上填充,数据网格将卡住,直到加载所有数据,然后显示数据网格。因此,我创建了另一个线程,将数据添加到数据网格中。但它向我显示错误。跨线程通信。
我的代码如下。
private void btnStartTest_Click(object sender, EventArgs e)
{
tbCtrl.Visible = true;
viewData.Show();
viewData.ScrollBars = ScrollBars.None;
//tbCtrl.Size = MaximumSize;
Thread thr = new Thread(LoadData);
thr.Start();
}
public void LoadData()
{
for (int i = 0; i < 20; i++)
{
int firstDisplayed = viewData.FirstDisplayedScrollingRowIndex;
int displayed = viewData.DisplayedRowCount(true);
int lastVisible = (firstDisplayed + displayed) - 1;
int lastIndex = viewData.RowCount - 1;
viewData.Rows.Add();
if (lastVisible == lastIndex)
{
viewData.FirstDisplayedScrollingRowIndex = firstDisplayed + 1;
}
viewData.Rows[i].Cells[0].Value = System.DateTime.Now.Hour + ":" +
for (int j = 1; j < 7; j++)
{
viewData.Rows[i].Cells[j].Value = (i + j).ToString();
}
Thread.Sleep(1000);
}
}
请告诉我如何在不挂起 UI 的情况下实现这一目标。我没有从数据库中提取数据。无需进行任何计算。
最佳答案
您可以在工作线程内访问 viewData,但并非没有可能(且不确定)的问题。简而言之:这样做并不安全。我知道的最简单的方法是创建一个新的公共(public)静态类,例如这个(类的名称并不重要,实际上可以是您想要的任何名称,因为它仅用于扩展方法),然后将这两个方法放入该类中如下:
static partial class MyExtensions
{
public static TResult SafeInvoke<T, TResult>(this T isi, Func<T, TResult> callFunction) where T : ISynchronizeInvoke
{
if (isi.InvokeRequired)
{
IAsyncResult result = isi.BeginInvoke(callFunction, new object[] { isi });
object endResult = isi.EndInvoke(result); return (TResult)endResult;
}
else
return callFunction(isi);
}
/// <summary>
/// This can be used in C# with:
/// txtMyTextBox.SafeInvoke(d => d.Text = "This is my new Text value.");
/// or:
/// txtMyTextBox.SafeInvoke(d => d.Text = myTextStringVariable);
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="isi"></param>
/// <param name="callFunction"></param>
public static void SafeInvoke<T>(this T isi, Action<T> callFunction) where T : ISynchronizeInvoke
{
if (isi.InvokeRequired) isi.BeginInvoke(callFunction, new object[] { isi });
else
callFunction(isi);
}
} // static class MyExtensions
然后每次您在 LoadData() 方法中访问 viewData
变量时,您都需要使用这些方法来访问它。这些方法以“安全”的方式调用这些方法。因此 viewData.Rows.Add();
将替换为 viewData.SafeInvoke(d => d.Rows.Add());
。
要了解发生了什么,您可以阅读扩展方法和 lambda 表达式。但这是我见过的最干净的方法。我见过很多其他方法,但大多数都复杂两倍以上。我几年前复制了这段代码,因为这并不是一个罕见的问题。快乐编码! :)
关于c# - 访问数据网格时的跨线程通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20062869/