2013-02-25 5 views
0

Я создал программу-образец, которая генерирует каждые 2000 целых чисел в фоновом потоке, а когда она заканчивается, запускается событие, которое рисует график в графическом интерфейсе из случайных сгенерированных данных (у меня есть спать внутри моей нити, чтобы имитировать реальное измерение).Доступ к графическому интерфейсу из фонового потока

private void SetChart(System.Windows.Forms.DataVisualization.Charting.Series series) 
{ 
    if (InvokeRequired) 
    { 
    SetChartCallback d = new SetChartCallback(SetChart); 
    this.Invoke(d, new object[] { series }); 
    } 
    else 
    { 
    chart1.Series[0] = series; 
    chart1.Series[0].Name = "Generated Data"; 
    } 
} 

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

Невозможно получить доступ к расположенному объекту.
Название объекта: 'Form1'.

Когда я закрываю программу, она располагает всеми элементами, как я могу предотвратить эту ошибку?

+3

Рекомендованный подход заключается в том, чтобы не закрывать форму до тех пор, пока все ваши фоновые потоки не будут завершены. например отключить закрытое масло или переопределить событие закрытия, чтобы сообщить пользователю, что что-то в данный момент происходит в фоновом режиме, и повторить попытку позже. В противном случае, если вы закроете форму, она исчезнет, ​​пока фоновая обработка все еще происходит ... –

+0

Теперь я проверяю значение Thread.IsAlive boolean, но если он возвращает true, и я вызываю thread.Join() - программу зависает и ничего не происходит. – patex1987

+0

Где вы называете thread.join? если вы назовете это в конце формы, он будет блокироваться до тех пор, пока ваш фоновый поток не завершится - это то, что делает Join. –

ответ

0

Решение может заключаться в проверке IsDisposed. Что-то вроде этого:

private void SetChart(System.Windows.Forms.DataVisualization.Charting.Series series) 
{ 
    if (IsDisposed) 
     return; 

    // ... 
} 
+0

Извините, но похоже, что это не решает проблему. То же самое происходит, как и до – patex1987

1

Вы закрыли форму, но поток все еще работает, поэтому, когда он завершает он пытается вызвать метод на выбывшего объекта. Ваша форма.

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

Не поддавайтесь соблазну просто убить его. Очень дурная привычка, вы не хотите вникать в это.

+0

В событии Form.FormClosed я проверяю состояние Thread.IsAlive. Когда он возвращает true, я пытаюсь присоединиться() к потоку (или есть ли другой способ подождать, пока поток выполнит свою задачу?), Потому что при вызове метода Join вся программа зависает. – patex1987

+0

Регистрация будет подождать, но это заморозит вашу основную нить. Завершает ли поток завершение. Если это не так, вы никогда не закончите, пока не сообщите об этом. –

+0

Как я могу завершить поток при завершении? – patex1987

1

Правильный подход, уродливый, как может показаться, вероятно, поймать исключение и проглотить его. Вероятно, не разумно, чтобы форма Dispose блокировалась до тех пор, пока фоновый поток не выйдет (ситуация, которая может легко вызвать тупик); ни Рамки не предоставляют какой-либо метод, который говорит о попытке установить Invoke или BeginInvoke этот метод в элементе управления или форме, но просто ничего не делать, если он был удален. Таким образом, ваш лучший выбор - это, вероятно, написать TryInvoke и TryBeginInvoke методы, которые сделают это, поймав любое исключение, которое получится, если форма была удалена. Вы можете использовать проверку IsDisposed внутри такого метода, но вы должны понимать, что из-за некоторых особенностей Query существуют некоторые условия гонки, которые не могут быть успешно решены.

Смежные вопросы