Дедлок в WinForms, который предотвращается нажатием правой кнопки мыши на панели задач

Я столкнулся со странной проблемой с нашим приложением Windows C # / .NET. На самом деле это приложение с графическим интерфейсом, моя работа - это сетевой компонент, включенный в сборку.Я не знаю код основного приложения / приложения с графическим интерфейсомЯ мог связаться с нимРазработчик, хотя.

Теперь приложениеУ пользовательского интерфейса есть кнопки для "Начните" а также "Стоп" сетевой движок. Обе кнопки работают. Чтобы сделать мой компонент безопасным для потоков, я использую блокировку вокруг трех методов. Я не'Я не хочу, чтобы клиент мог вызывать Stop () до завершения Start (). Кроме того, есть таймер опроса.

Я попытался показать вам как можно меньше строк и упростил задачу:

private Timer actionTimer = new Timer(new
                TimerCallback(actionTimer_TimerCallback),
                null, Timeout.Infinite, Timeout.Infinite);

public void Start()
{
 lock (driverLock)
 {
  active = true;
  // Trigger the first timer event in 500ms
  actionTimer.Change(500, Timeout.Infinite);
 }
}

private void actionTimer_TimerCallback(object state)
{
 lock (driverLock)
 {
  if (!active) return;
  log.Debug("Before event");
  StatusEvent(this, new StatusEventArgs()); // it hangs here
  log.Debug("After event");
  // Now restart timer
  actionTimer.Change(500, Timeout.Infinite);
 }
}

public void Stop()
{
 lock (driverLock)
 {
  active = false;
 }
}

Вот как воспроизвести мою проблему. Как я уже сказал, обе кнопки Start и Stop работают, но если вы нажмете Start (), иво время выполнения TimerCallback нажмите Stop ()это предотвращает возврат TimerCallback. Он висит точно в той же позиции, StatusEvent. Таким образом, блокировка никогда не снимается и графический интерфейс также зависает, потому чтоВызов метода Stop () не может быть продолжен.

Теперь я заметил следующее: если приложение зависает из-за этоготупиковой» и я щелкаю приложение на панели задач правой кнопкой мыши, оно продолжается. Это просто работает, как и ожидалось. У кого-нибудь есть объяснение или лучшее решение для этого?

Кстати, я также попробовал это с InvokeIfRequired, так как я неНе знаю, как работает приложение GUI. Это необходимо, если мой StatusEvent что-то изменит в GUI. Поскольку у меня нет ссылок на элементы управления GUI, я использовал (предполагая только одну цель):

Delegate firstTarget = StatusEvent.GetInocationList()[0];
ISynchronizeInvoke syncInvoke = firstTarget.Target as ISynchronizeInvoke;
if (syncInvoke.InvokeRequired)
{
  syncInvoke.Invoke(firstTarget, new object[] { this, new StatusEventArgs() });
}
else
{
  firstTarget.Method.Invoke(firstTarget.Target, new object[] { this, new StatusEventArgs() });
}

Этот подход неизменить проблему. Я думаю, это потому, что я вызываю основное приложение.обработчики событий, а не на элементах управления GUI. То есть основное приложение отвечает за Invoking? Но в любом случае AFAIK, не использующий Invoke, хотя и необходимый, не приведет к тупику, подобному этому, но (надеюсь) к исключению.

Ответы на вопрос(6)

Ваш ответ на вопрос