首页 文章

C#中使用Mono的交叉线程形式

提问于
浏览
0

我正在创建一个使用.Net和Mono的应用程序,它使用跨线程表单,因为我从子窗口得到了错误的响应 .

我用2种形式创建了一个测试程序:第一个(form1)有一个按钮(button1),第二个(form2)是空白的,下面是代码片段 .

void openForm()
{
    Form2 form2 = new Form2();
    form2.ShowDialog();
}
private void button1_Click(object sender, EventArgs e)
{
    Thread x = new Thread(openForm);
    x.IsBackground = true;
    x.Start();
}

这在.Net中运行良好,但是使用Mono时,第一个窗口在单击它时不会获得焦点(标准.ShowDialog()行为)而不是.Net使用的.Show()行为 .

当我使用.Show()时,在.Net和Mono上,窗口只是闪烁然后消失 . 如果我在'form2.Show()之后放置一个'MessageBox.Show()',它将保持打开状态,直到你单击OK .

我错过了该代码中的某些内容,还是Mono不支持? (我正在使用Mono 2.8.1)

先谢谢,阿德里安

编辑:我意识到我忘了'x.IsBackground = true;'在上面的代码中,子窗口将关闭主窗口 .

2 回答

  • 0

    如果使用Winforms控件,则总是在主UI线程中“触摸”对象 .

    至少 - 在新线程中调用新的Form.ShowDialog()没有意义 .

    EDIT: 如果您希望使用Invoke / BeginInvoke轻松工作,可以使用扩展方法:

    public static class ThreadingExtensions {
        public static void SyncWithUI(this Control ctl, Action action) {
            ctl.Invoke(action);
        }
    }
    // usage:
    void DoSomething( Form2 frm ) {
        frm.SyncWithUI(()=>frm.Text = "Loading records ...");
    
        // some time-consuming method
        var records = GetDatabaseRecords();
        frm.SyncWithUI(()=> {
            foreach(var record in records) {
                frm.AddRecord(record);
            }
        });
    
        frm.SyncWithUI(()=>frm.Text = "Loading files ...");
    
        // some other time-consuming method
        var files = GetSomeFiles();
        frm.SyncWithUI(()=>{
            foreach(var file in files) {
                frm.AddFile(file);
            }
        });
    
        frm.SyncWithUI(()=>frm.Text = "Loading is complete.");
    }
    
  • 1

    在Windows应用程序中执行多个线程与一个窗口或多个共享相同消息泵的窗口几乎不是正确的事情 .

    并且很少需要有多个消息泵 .

    正确的方法是使用“调用”方法手动封送从工作线程返回到窗口的所有内容,或者使用像BackgroundWorker这样的东西来隐藏详细信息 .

    综上所述:

    • 不要阻止UI线程进行耗时的计算或I / O.

    • 不要从多个线程与UI通信 .

相关问题