Control.BeginInvoke - 我如何*真正*使用它来获取winforms中的线程安全UI线程更新

时间:2014-03-26 15:08:18

标签: c# multithreading winforms ui-thread begininvoke

我完全理解这个问题的线程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#中执行此操作?

0 个答案:

没有答案