C # Добавление кода в событие FormClosing отключает X на MdiParent - PullRequest
1 голос
/ 05 января 2011

У меня есть два фоновых потока и поток для минимизации, выполняемый в моем приложении WinForms. Когда программа закрывается, я использую этот метод.

private void MyForm_Closing(object sender, FormClosingEventArgs e)
    {
        if(labelsUpdaterThread.IsAlive == true)
            labelsUpdaterThread.Abort();
        if(printNotifyThread.IsAlive == true)
            printNotifyThread.Abort();
        if(minimizeThread.IsAlive == true)
            minimizeThread.Abort();
    }

tagsUpdaterThread и printNotifyThread выполняются постоянно. MinimizeThread, как вы можете догадаться, запускается только тогда, когда родительская форма свернута. Вот моя проблема:

Когда методы thread.abort вызываются в моем методе выше, «X» в правом верхнем углу моей формы MdiParent ничего не делает. Нажав на это не имеет никакого эффекта.

Когда методы thread.abort НЕ вызываются в моем методе выше, закрытие MdiParent иногда вызывает исключения, поскольку потоки все еще пытаются получить доступ к ресурсам на MdiParent, которые больше не доступны, даже если они являются фоновыми потоками!

Я не уверен, почему это происходит, для меня это не имеет особого смысла. Заранее спасибо за любую помощь!

Ответы [ 3 ]

4 голосов
/ 05 января 2011

Я согласен с ответом Пола Александра в том, что вы должны никогда звонить Thread.Abort, это ужасный способ справиться с синхронизацией.

Кроме того, у вас здесь ужасное разделение интересов. Потоки не должны обращаться к ресурсам в форме напрямую. Между ними должна быть какая-то абстракция / разделяемое состояние, которое изменяется и читается обеими сторонами (потоком и формой, поэтому убедитесь, что экземпляр является потокобезопасным).

Тем не менее, если вы не можете внести эти изменения, тогда в методе Close вызовите методы Thread.Abort в другом потоке с оператором try / catch вокруг каждого. Зарегистрируйте ошибки где-нибудь хотя бы.

Выполняя вызовы Thread.Abort в другом потоке, вы не блокируете поток пользовательского интерфейса, поскольку не гарантируется, что вызовы Thread.Abort будут мгновенными, а блокировка потока пользовательского интерфейса вызовет серый цвет X в то время как поток пользовательского интерфейса не может обрабатывать сообщения Windows (это также поможет вам лучше разделить проблемы).

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

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

Оттуда вы можете ввести надлежащий механизм совместного отмены ( совместное отмену, которое Task поддерживает в .NET 4.0 , если он вам доступен).

0 голосов
/ 05 января 2011

Во-первых, удалите вызовы .Abort () и никогда не используйте их снова. Потоки никогда не должны прерываться вызовом Abort. Это в основном приводит к краху вашего потока и не дает ему возможности правильно освободить любые ресурсы или освободить системные дескрипторы. Вместо этого создайте ManualResetEvent и проверьте это в своих темах. Когда событие установлено, они должны завершиться.

Резьба1

while( ! _stopEvent.WaitOne(0) )
{
  ...do my thready work

}

Затем в заключение

private void MyForm_Closing(object sender, FormClosingEventArgs e)
{
  _stopEvent.Set();
  labelsUpdaterThread.Join();
  ...
}

Если вам все равно, правильно ли завершаются потоки в существующем приложении, просто установите IsBackground = true, и они будут завершены автоматически при выходе из приложения.

0 голосов
/ 05 января 2011

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

И в Visual Studio откройте Debug \ Exceptions ... и установите в столбце «выбросить» флажок для всех исключений, чтобы вы могли видеть, когда что-то идет не так.

...