Как распознать ошибку?
Приложение полностью замораживает. Нечего сделать ничего, кроме как создать дамп памяти, а затем закройте его через TaskManager. Если вы откроете файл DMP в VisualStudio или WindBG, вы можете увидеть трассировку стека, подобное этому < /p>
Код: Выделить всё
WaitHandle.InternalWaitOne
WaitHandle.WaitOne
Control.WaitForWaitHandle
Control.MarshaledInvoke
Control.Invoke
WindowsFormsSynchronizationContext.Send
System.EventInvokeInfo.Invoke
SystemEvents.RaiseEvent
SystemEvents.OnUserPreferenceChanged
SystemEvents.WindowProc
:
какова причина? Это дает нам такие методы, как «begininvoke» и тому подобное. Он будет запускается пользователем, изменяющим свой фон, входит в систему или выезд, изменяя цветы акцента Windows и множество других действий. Некоторые элементы управления графическим интерфейсом подписываются на событие UserPreferenceChanged при создании или при использовании определенных методов. Если это событие запускается пользователем, основной поток отправляет сообщение всем подписчикам и ожидает. В описанном сценарии: рабочая потока без цикла сообщения! Приложение заморожено. < /P>
Чтобы найти причину замораживания, может быть особенно жесткой, потому что причина ошибки (создание элемента графического интерфейса в фоновом потоке) и состояние ошибки (замороженное приложение) может быть с интервалом в минутах. Смотрите эту действительно хорошую статью для более подробной информации и немного другого сценария. https://www.ikriv.com/dev/dotnet/mysterioushang> Примеры
Как можно спровоцировать эту ошибку для целей тестирования?private void button_Click(object sender, EventArgs e)
{
new Thread(DoStuff).Start();
}
private void DoStuff()
{
using (var r = new RichTextBox())
{
IntPtr p = r.Handle; //do something with the control
}
Thread.Sleep(5000); //simulate some work
}
< /code>
Неплохо, но тоже не очень хорошо. Если событие userpreferenceChanged запускается в нескольких миллисекундах, которые вы используете RichTextBox, которое ваше приложение замораживает. Может случиться, если не очень вероятно. < /P>
Пример 2 < /p>
private void button_Click(object sender, EventArgs e)
{
new Thread(DoStuff).Start();
}
private void DoStuff()
{
var r = new RichTextBox();
IntPtr p = r.Handle; //do something with the control
Thread.Sleep(5000); //simulate some work
}
< /code>
Это плохо. WindowsFormSsyNchronizationContext не очищается, потому что RichTextBox не утилизируется. Если userpreferenceChangeDevent происходит, пока поток живет, ваше приложение замерзает. < /P>
Пример 3 < /p>
private void button_Click(object sender, EventArgs e)
{
Task.Run(() => DoStuff());
}
private void DoStuff()
{
var r = new RichTextBox();
IntPtr p = r.Handle; //do something with the control
}
< /code>
Это кошмар. Task.Run (..) выполнит работу на фоновом потоке на потоке. WindowsFormSsyNchronizationContext не очищается, потому что RichTextBox не утилизируется. Темкотичные потоки не очищаются. Этот фоновый поток теперь скрывается в вашем потоке, просто ожидая события UserPreferenceChanged, чтобы заморозить ваше приложение даже через долгое время после возвращения вашей задачи! Но когда это возможно: избегайте элементов графического интерфейса в фоновом потоке!
Как справиться с этой ошибкой?
Подробнее здесь: https://stackoverflow.com/questions/704 ... ts-userpre
Мобильная версия