2013-09-14 2 views
2

Кажется случайным, что я получу исключение перекрестной резьбы при выполнении моего приложения формы выигрыша. Вот как я пытаюсь управлять им:Непредсказуемое исключение кросс-потоков

private void ToOutput(string s) 
{ 
    if (!this.IsHandleCreated) 
     this.CreateHandle(); 

    if (FormOutputArea.InvokeRequired) 
    { 
     FormOutputArea.Invoke(new Action(delegate() 
     { 
      FormOutputArea.AppendText(s + Environment.NewLine); 
     })); 
    } 
    else 
    { 
     FormOutputArea.AppendText(s + Environment.NewLine); 
    } 
} 

Оказывается InvokeRequired не всегда точны. Я пробовал BeginInvoke с тем же результатом.

EDIT: Даже когда я проверяю IsHandleCreated и InvokeRequired с помощью контрольных точек они настроены так, однако else ветвь состояния выполняется.

Вот скриншот, показывающий, где исключение теперь брошено:

enter image description here

+0

Возможно, вы захотите посмотреть на следующее: http://stackoverflow.com/questions/808867/invoke-or-begininvoke-cannot-be-called-on-a-control-until-the-window-handle- имеет – Styxxy

+0

Даже ручка управления проверкой не помогла. Я сбив с толку, почему исключение потока выбрасывается один раз, когда выполняется пять раз (вероятность 20%) подряд. – Lee

+0

* Даже когда я проверяю IsHandleCreated и InvokeRequired с помощью точек останова, они установлены в true, но ветвь else выполняется. * Можете ли вы показать этот код, что вы пробовали в этом? –

ответ

5

Ввод CreateHandle() и InvokeRequired в тот же метод в корне неверно. Это будет взрываться, когда дескриптор еще не создан, вы создадите собственное окно в неправильном потоке. Окно дочернего контроля должно быть принадлежать той же теме, которая владеет формой, и этот поток должен накачать контур сообщения (Application.Run).

Простым обходным путем является обеспечение того, чтобы поток не запускался до тех пор, пока не будет создано окно формы. Который также создаст окна всех элементов управления, встроенных в эту форму. Самое раннее, что происходит, - это событие загрузки. В этот момент вы можете доверять InvokeRequired, чтобы быть точным.

Остерегайтесь проблем, когда пользователь закрывает форму, ваш исходный код будет вести себя очень плохо, если вы разрешите продолжить поток. Пока неясно, боишь ли ты код перед созданием окна формы или после его закрытия. Вы должны убедиться, что поток остановлен или больше не может вызвать ToOutput(). Предметом this answer.

+0

Спасибо, Ханс, я думаю, что разобрал проблему. У меня были инициализированы фоновые потоки и запущены в конструкторе формы. Я переместил их в событие _Load, которое, похоже, отсортировало его! К счастью, проблема более простая, чем я ожидал. – Lee

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