简体   繁体   中英

Cross-threading forms in C# with Mono

I'm creating an application that uses .Net and Mono, it uses cross-threaded forms as I was having bad response from the child windows.

I created a test program with 2 forms: the first (form1) has a single button (button1) and the second (form2) is blank, code snippet below.

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();
}

This works fine in .Net, but with Mono, the first window will not gain focus when you click it (standard .ShowDialog() behaviour) rather than .Show() behaviour as .Net uses.

When I use .Show(), on .Net and Mono the window just flashes then disappears. If I put a 'MessageBox.Show()' after 'form2.Show()' it will stay open until you click OK.

Am I missing something in that code or does Mono just not support that? (I'm using Mono 2.8.1)

Thanks in advance, Adrian

EDIT: I realised I forgot 'x.IsBackground = true;' in the code above so child windows will close with the main window.

It's almost never the right thing to do in a Windows app to have more than one thread talk to one window or multiple windows which share the same message pump.

And it's rarely necessary to have more than one message pump.

The right way to do this is either to manually marshal everything back from your worker threads to your Window, using the 'Invoke' method, or use something like BackgroundWorker, which hides the details for you.

In summary:

  • Don't block the UI thread for time-consuming computation or I/O
  • Don't talk to the UI from more than one thread.

If you use Winforms controls, you shold "touch" the object always in main UI thread.

And at least - calling new Form.ShowDialog() in new thread does not make sense.

EDIT: If you want easy work with Invoke/BeginInvoke you can use extension methods:

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.");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM