我完全理解这个问题的线程logisitics,所以我知道“我想做什么”,但我很难用C#的实现。
以下是场景:我想以线程安全的方式将整个控件传递给UIThread,以便将表单附加到panel
。需要以某种方式生成此控件。可能使用BeginInvoke。如果我能得到一些帮助,这将是很好的。
我有一种感觉,如果我传递包含可能足够的控制数据的第三方类:这里是线程代码:
/****
* scan the UIThread to decide if the frmVerdict needs to be shown,
* and if neccesary centre it upon the frmMain if that is also shown
* either way post an actionable update to frmVerdict or create it
*/
FormCollection fc = Application.OpenForms;
frmVerdict form = null;
frmMain parent = null;
foreach (Form frm in fc)
{
if (frm is frmVerdict)
{
form = (frmVerdict)frm;
}
if (frm is frmMain)
{
parent = (frmMain)frm;
}
}
if (form == null)
{
form = new frmVerdict();
if (parent != null)
{
form.StartPosition = FormStartPosition.Manual;
form.Location = new Point(parent.Location.X + (parent.Width - form.Width) / 2, parent.Location.Y + (parent.Height - form.Height) / 2);
}
form.ShowDialog(); //f.ShowDialog(this)
}
form.addAction(action);
form.BringToFront();
在表单中我有这段代码(在frmVerdict
内的其他内容)
public void addAction(classActionType action)
{
elementCounter++;
TextBox txtbx = new TextBox(); //TextBox txtbx = (TextBox)Controls["txtbx0001"];
txtbx.Text = action.thisFileOrFolder.folder.localFolder;
txtbx.Name = "txtbx" + elementCounter.ToString().PadLeft(4, '0');
txtbx.Location = new Point(10, 15 * elementCounter);
txtbx.Height = 20;
txtbx.Width = 50;
pnlVerdict.Controls.Add(txtbx); //this line crashes with Cross-thread operation not valid: Control 'pnlVerdict' accessed from a thread other than the thread it was created on.
thingsToDo.Add(action);
}
这个想法是线程类会决定UIThread是否有form
frmVerdict的实例,如果有的话,以控件的形式发布更新,或者如果不是只是弹出frmVerdict,这是一个信息响应/必需集。然后,用户所需的决定可以排队。 (想象一下如果一个表格出现并问你一个问题然后淡化“咆哮”另一个问题,那么它会咆哮第三个等等,因为线程在后台运行。)
问题是我得到Cross-thread operation not valid: Control 'pnlVerdict' accessed from a thread other than the thread it was created on.
(这是我所期望的)。我需要做的是Control.BeginInvoke
UIThread上的(classActionType action)
,但 如何在C#中执行此操作?