Сложный многопоточный интерфейс - PullRequest
2 голосов
/ 18 ноября 2010

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

У меня есть форма, которая запускаетN количество потоков (я не знаю, сколько, пользователь должен выбрать) ... у каждого потока есть объект, и в течение нескольких моментов объекты могут вызывать событие, чтобы сигнализировать о некотором изменении ... должна быть форма для каждого потока«сообщать» о сообщениях, отправляемых событиями ...

Моя проблема в том, что потоки создают формы идеально ... но исчезают ... из ниоткуда ... они появляются на экране... и исчезнуть ... пуф ... ушел!как я могу избежать этого нежелательного "избавления"?!?!

Ответы [ 3 ]

2 голосов
/ 18 ноября 2010

Ваши потоки должны либо

  • использовать правильную логику InvokeRequired + Invoke
  • , либо запустить собственный MessagePump (Application.Run)

Какой из них сделалВы (не) делаете?

1 голос
/ 18 ноября 2010

Если вы создаете форму в потоке, форма исчезнет, ​​когда поток будет завершен.Если вы хотите, чтобы форма просуществовала дольше, вам нужно либо сохранить поток в рабочем состоянии, либо создать форму в главном потоке приложения.Последнее было бы предпочтительнее.Просто убедитесь, что каждый подключил прослушиватель событий для объекта в соответствующей форме, и используйте Invoke или BeginInvoke при необходимости при обновлении формы.

Простой пример:

Первый работник: класс Worker {public event EventHandler SomethingHappened;

    protected void OnSomethingHappened(EventArgs e)
    {
        var evnt = SomethingHappened;
        if (evnt != null)
        {
            evnt(this, e);
        }
    }
    public void Work()
    {
        // do lots of work, occasionally calling
        // OnSomethingHappened
    }
}

Затем в форме у нас есть обработчик события для события SomethingHappened:

public void SomethingHappenedHandler(object sender, EventArgs e)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action(() => SomethingHappenedHandler(sender, e)));
        return;
    }

    // update gui here
}

Тогда на самом деле нужно просто соединить все вместе:

Worker w = new Worker();
ProgressForm f = new ProgressForm;
w.SomethingHappened += f.SomethingHappenedHandler; 
f.Show();   
Thread t = new Thread(w.Work);
t.Start();

Отказ от ответственности: этот образец быстро подбрасывается и несколько не проверяется (сидя в поезде, вот-вот сойдет;)).

1 голос
/ 18 ноября 2010

A Form должен размещаться в потоке с циклом сообщений.Вы можете создать цикл сообщений, вызвав Application.Run или Form.ShowDialog.Однако, если у вас нет действительно веских причин для этого, я бы избегал иметь более одного потока с циклом сообщений Windows.

Я бы также не стал создавать N потоков.Существуют лучшие способы распараллеливания N операций, кроме создания одного потока на операцию.Чтобы назвать только два: 1) поставить в очередь рабочий элемент в ThreadPool или 2) использовать параллельную библиотеку задач через класс Task.Проблема с созданием N потоков состоит в том, что каждый поток потребляет определенное количество ресурсов.Больше потоков означает, что будет использовано больше ресурсов и произойдет переключение контекста.Больше не всегда лучше в мире многопоточности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...