Почему происходит зависание формы и таймеров windwos forms?

Здравствуйте.

Есть приложение windows forms, которое работает из трея. В трее висит значок, приложение работает преимущественно в свернутом виде.
В приложении используется несколько потоков, которые работают с picturebox. Перед изменением свойств picturebox я его блокирую:
lock (pictureBox)
   {
      var updateAction = new Action(() =>
      {
         pictureBox.Image = s.Image;
      }
   }


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

НО самое интересное, при вызове контекстного меню из иконки в трее все размораживается, причем в зависимости от времени простоя срабатывают все события, которые должны были выполнится в это время.
Например, есть таймер, вызывающий каждую секунду событие. Если вызовем меню из трея через 60 секунд после "зависания", все разморозится и событие таймера мгновенно выполнится 60 раз. Такое поведение только в скомпилированной версии приложения, если запускать из оболочки Visual Studio то такого эффекта добиться не удается, поэтому есть трудность с тем, чтобы отловить этот баг.

Что искать? В какую сторону смотреть?
  • Вопрос задан
  • 3764 просмотра
Решения вопроса 1
Nipheris
@Nipheris Куратор тега C#
Работать с UI, то есть с формами и контролами, из потока, НЕ породившего эту форму/контрол - очень плохая практика, которая рано или поздно приводит к таким проблемам, как ваша. Кроме того, она еще и усложняет отладку.

Вне зависимости от того, какие у вас там вычисления, выполняйте их отдельно, складывайте результат в массив/Bitmap, а уже в UI-потоке по таймеру регулярно считывайте рассчитанные данные и отображайте в PictureBox.

Даже если проблема не исчезнет, вам будет проще определить, где происходит зависание. Сейчас это может быть по куче различных причин. Повторюсь: то, что вы лочите pictureBox это не решение проблемы - в WinAPI НЕЛЬЗЯ работать с UI напрямую из другого потока, а WinForms это не более чем обертка над стандартными контролами.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@tex0
То о чем говорит Станислав Макаров не совсем верно ибо существует очень много случаев, когда вам необходимо изменять контрол из стороннего потока (так то вообще да - если есть возможность избегать изменения контрола в стороннем потоке - избегайте). Ваш lock тут не поиможет. Для этого существует Control.InvokeRequired.
(А вообще, если говорить о графических приложениях, я вам советую перейти с WinForms на WPF.)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы