Скрещенные формы в C # с Mono - PullRequest
0 голосов
/ 06 апреля 2011

Я создаю приложение, которое использует .Net и Mono, оно использует многопоточные формы, поскольку я получаю плохой ответ от дочерних окон.

Я создал тестовую программу с 2 формами: первая (форма1) имеет одну кнопку (кнопка1), а вторая (форма2) пуста, фрагмент кода ниже.

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 ()), а не .Show (), как .Net использует.

Когда я использую.Show (), на .Net и Mono окно просто мигает, а затем исчезает.Если я добавлю «MessageBox.Show ()» после «form2.Show ()», он останется открытым, пока вы не нажмете «ОК».

Я что-то упустил в этом коде или Mono просто не поддерживает это?(Я использую Mono 2.8.1)

Заранее спасибо, Адриан

РЕДАКТИРОВАТЬ: я понял, что я забыл 'x.IsBackground = true;'в приведенном выше коде, поэтому дочерние окна закроются с основным окном.

Ответы [ 2 ]

1 голос
/ 06 апреля 2011

В приложении для Windows почти никогда не следует делать так, чтобы несколько потоков говорили с одним окном или несколькими окнами, использующими один и тот же насос сообщений.

И редко нужно иметь более одногоmessage pump.

Правильный способ сделать это - либо вручную перенаправить все обратно из рабочих потоков в окно, используя метод Invoke, либо использовать что-то вроде BackgroundWorker, который скрывает детали для вас.

В итоге:

  • Не блокируйте поток пользовательского интерфейса для трудоемких вычислений или ввода-вывода
  • Не говорите с пользовательским интерфейсом из более чемодна нить.
0 голосов
/ 06 апреля 2011

Если вы используете элементы управления Winforms, вы должны "касаться" объекта всегда в основном потоке пользовательского интерфейса.

И, по крайней мере, вызов нового 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.");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...