控件 'x' 从创建它的线程以外的线程访问
Control 'x' accessed from a thread other than the thread it was created on
winform 应用程序,我有一个网格视图和数据源填充(在绑定函数上)由委托开始调用 sapareted 线程,但 gridView 数据源无法从新线程获取生成的值,因为 gridview 是在主线程上创建的:
这里我调用新线程
private void button_selectFile_Click(object sender, EventArgs e)
{
if (resultLoadingFile == DialogResult.OK)
{
filename = openFileDialog_logLoader.FileName;
string name = System.IO.Path.GetFileName(filename);
label_selectFileStatus.Text = name;
readDelegate parseAndSplit = new readDelegate(ReadLogFileAndDrawTable);
AsyncCallback cb = new AsyncCallback(doneReadFile);
IAsyncResult ar = parseAndSplit.BeginInvoke(filename, cb, dataGridView_mainTable);
}
}
这里我调用bind:
private void doneReadFile(IAsyncResult ar)
{
Bind();
}
这是 Bind():
private void Bind(){
TableLoadMgr.ItemsLoaded = TableModelListFiltered.Count();
updateLoadedStatus();
//The following line throw exception:
dataGridView_mainTable.DataSource = TableModelListFiltered;
}
确切的问题是:
我如何在主线程上触发 Bind(),因为回调函数在新的委托线程上触发。
备注:
- 我看到的重复主题问题没有回答 winform 和约束
- 计时器不是一个选项
- 新用户触发器(例如线程完成后的按钮 "show")不是一个选项
您的 AsyncResult 将有一个 AsyncState,它包含对您的 DataGridView 的引用。因此,您可以使用该控件来检查 Bind()
是否需要上下文切换,如果是,则使用该控件的 Invoke 来切换线程:
private void doneReadFile(IAsyncResult ar)
{
var ctl = ar.AsyncState as System.Windows.Forms.Control; // the control
if (ctl != null && ctl.InvokeRequired) { // is Invoke needed?
// call this method again, but now on the UI thread.
ctl.Invoke(new Action<IAsyncResult>(doneReadFile), ar);
} else {
Bind();
}
}
winform 应用程序,我有一个网格视图和数据源填充(在绑定函数上)由委托开始调用 sapareted 线程,但 gridView 数据源无法从新线程获取生成的值,因为 gridview 是在主线程上创建的:
这里我调用新线程
private void button_selectFile_Click(object sender, EventArgs e)
{
if (resultLoadingFile == DialogResult.OK)
{
filename = openFileDialog_logLoader.FileName;
string name = System.IO.Path.GetFileName(filename);
label_selectFileStatus.Text = name;
readDelegate parseAndSplit = new readDelegate(ReadLogFileAndDrawTable);
AsyncCallback cb = new AsyncCallback(doneReadFile);
IAsyncResult ar = parseAndSplit.BeginInvoke(filename, cb, dataGridView_mainTable);
}
}
这里我调用bind:
private void doneReadFile(IAsyncResult ar)
{
Bind();
}
这是 Bind():
private void Bind(){
TableLoadMgr.ItemsLoaded = TableModelListFiltered.Count();
updateLoadedStatus();
//The following line throw exception:
dataGridView_mainTable.DataSource = TableModelListFiltered;
}
备注:
- 我看到的重复主题问题没有回答 winform 和约束
- 计时器不是一个选项
- 新用户触发器(例如线程完成后的按钮 "show")不是一个选项
您的 AsyncResult 将有一个 AsyncState,它包含对您的 DataGridView 的引用。因此,您可以使用该控件来检查 Bind()
是否需要上下文切换,如果是,则使用该控件的 Invoke 来切换线程:
private void doneReadFile(IAsyncResult ar)
{
var ctl = ar.AsyncState as System.Windows.Forms.Control; // the control
if (ctl != null && ctl.InvokeRequired) { // is Invoke needed?
// call this method again, but now on the UI thread.
ctl.Invoke(new Action<IAsyncResult>(doneReadFile), ar);
} else {
Bind();
}
}