Итак, у меня есть эта очень странная вещь в одном из приложений C# для клиентов. Это приложение WPF, использующее Media Foundation с помощью SharpDX. Цель состоит в том, чтобы воспроизводить рекламу с использованием заранее определенного списка воспроизведения. Компонент SharpDX абстрагируется в отдельной библиотеке, запущенной в собственном потоке, наряду с потоком пользовательского интерфейса WPF. Это работает очень хорошо!Task.Run и Wait deadlocking?
Часть реализации SharpDX - это планировщик плейлистов, который обеспечивает воспроизведение плейлиста в соответствии с инструкциями. Видео за 15 секунд ДЕЙСТВИТЕЛЬНО должно играть в течение 15 секунд.
В прошлом я использовал Thread
и ManualResetEvent
, чтобы иметь возможность запускать/останавливать планировщик по требованию. За один раз будет запускаться только один планировщик, поэтому эта работа задается вопросом.
Однако требования изменились, и теперь нам нужно одновременно воспроизводить несколько плейлистов, что также означает несколько планировщиков. Вскоре я начал замечать тупики по неизвестным причинам и решил, что просто «обновить» до Task
и CancelationToken
.
Вот фрагмент того, как она работает прямо сейчас:
private void CreateScheduleThread()
{
DestroyScheduleThread();
_cancellationTokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = _cancellationTokenSource.Token;
_task = Task.Run(
() => ScheduleThread(cancellationToken),
cancellationToken
);
}
private void DestroyScheduleThread()
{
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Cancel();
try
{
_task.Wait();
}
catch
{
//Do nothing
}
_cancellationTokenSource.Dispose();
_cancellationTokenSource = null;
}
}
private void ScheduleThread(CancellationToken cancellationToken)
{
while (true)
{
cancellationToken.ThrowIfCancellationRequested();
//Do more stuff
}
}
По мнению большинства интернет-примеров, это правильный способ установки отменяемой задачи. Когда мы создаем новый планировщик, мы должны убедиться, что предыдущий (в том же экземпляре класса, в котором он живет) разрушен, прежде чем продолжить. В этом когда возникает проблема.
Проблема: Когда у меня есть два планировщиков под управлением которых начали использовать CreateScheduleThread
, и я отменить их обоих на за другой, используя DestroyScheduleThread
, второй вызов будет иногда висеть на _task.Wait()
линии. Я не могу понять, почему он это делает ... и я не могу уверенно вызвать его.
При отладке ScheduleThread
-loop больше не работает, поэтому задача завершена. Однако при проверке _task
он утверждает, что он все еще работает.
Вопрос: У кого-нибудь есть ключ к тому, почему это происходит и что самое главное, как его исправить?
Вы не должны вызывать '_task.Wait()' из потока графического интерфейса. Поэтому мне интересно, какие интернет-примеры вы следовали. –
Пробовали ли вы использовать ConfigureAwaitf (false)? –
Я не знаю mcuh о задачах, но вы не используете то же самое cancelationToken для всех задач правильно? – null