C# 任务无法访问主线程中的控件
C# task can't access control in main thread
使用 Winforms、C#、FW 4.5。
我有一个带有文本框和 gridView 的简单表单。
当我开始一项新任务时,它能够访问网格的单元格并更改文本。当我尝试更改文本框文本时出现此错误 "cross thread operation not valid..."
文本框和gridView都在同一个窗体上。为什么行为不同?
从与启动 UI 的线程不同的线程访问您的 UI 通常不是一个好主意。可以通过将静态 属性 Control.CheckForIllegalCrossThreadCalls
设置为 false
来避免异常,但这是一种非常危险的方式。
您应该使用 Control.BeginInvoke
将执行推迟回 UI 线程。
因此您可以将行 txtSql.Text = sQuery
替换为类似的内容:
void RunChecks()
{
...
SetQueryText(sQuery); // instead of txtSql.Text = sQuery;
...
}
delegate void SetTextDelegate(string text);
void SetQueryText(string query)
{
if (txtSql.InvokeRequired)
{
txtSql.BeginInvoke(new SetTextDelegate(SetQueryText), query);
return;
}
txtSql.Text = query;
}
因此SetQueryText
检查是否有必要调用Invoke
(或BeginInvoke
),因为它是从另一个线程调用的。如果是这种情况,它调用 BeginInvoke
将执行推迟到 UI 线程和 returns.
不幸的是,这仍然使用委托语法而不是 lambda,但也许有更好的语法,我只是不知道。
您需要对从不同线程访问的所有控件执行此操作。
使用 Winforms、C#、FW 4.5。 我有一个带有文本框和 gridView 的简单表单。 当我开始一项新任务时,它能够访问网格的单元格并更改文本。当我尝试更改文本框文本时出现此错误 "cross thread operation not valid..."
文本框和gridView都在同一个窗体上。为什么行为不同?
从与启动 UI 的线程不同的线程访问您的 UI 通常不是一个好主意。可以通过将静态 属性 Control.CheckForIllegalCrossThreadCalls
设置为 false
来避免异常,但这是一种非常危险的方式。
您应该使用 Control.BeginInvoke
将执行推迟回 UI 线程。
因此您可以将行 txtSql.Text = sQuery
替换为类似的内容:
void RunChecks()
{
...
SetQueryText(sQuery); // instead of txtSql.Text = sQuery;
...
}
delegate void SetTextDelegate(string text);
void SetQueryText(string query)
{
if (txtSql.InvokeRequired)
{
txtSql.BeginInvoke(new SetTextDelegate(SetQueryText), query);
return;
}
txtSql.Text = query;
}
因此SetQueryText
检查是否有必要调用Invoke
(或BeginInvoke
),因为它是从另一个线程调用的。如果是这种情况,它调用 BeginInvoke
将执行推迟到 UI 线程和 returns.
不幸的是,这仍然使用委托语法而不是 lambda,但也许有更好的语法,我只是不知道。
您需要对从不同线程访问的所有控件执行此操作。