私はクライアントC#アプリケーションの1つにこの非常に奇妙なことがあります。 SharpDXを使用してMedia Foundationを使用するWPFアプリケーションです。目的は、所定のプレイリストを使用して広告を再生することである。 SharpDXコンポーネントは、WPFのUIスレッドと並んで、独自のスレッドで実行されている別のライブラリで抽象化されています。これはとてもうまくいきます!Task.Runとデッドロックが発生しましたか?
SharpDX実装の一部は、再生リストが指示どおりに再生されるようにする再生リストスケジューラです。 15秒のビデオは本当に15秒間再生する必要があります。
以前は、スケジューラをオンデマンドで開始/停止できるように、私はThread
とManualResetEvent
を使用していました。一度に1つのスケジューラしか実行しないので、この作業は不思議です。
しかし、要件が変更され、複数のプレイリストを同時に再生する必要があります。つまり複数のスケジューラも同時に再生する必要があります。まもなく私は不明な理由でデッドロックに気付きはじめ、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
を使用して開始された実行している2つのスケジューラを持っている、と私はDestroyScheduleThread
を使用して、他の後にそれらの両方でキャンセルすると、2回目の呼び出しは時折_task.Wait()
ラインにハングアップします。私はなぜそれがそれを行うかを世界が理解することはできません...私はそれを確実に引き起こすことはできません。
デバッグ時に、ScheduleThread
-loopは実行されていないため、タスクは完了しています。しかし、_task
を調べると、まだ実行中だと主張しています。
質問:なぜこれが起こるのか、そして最も重要なのは誰ですか?どのように修正するのですか?
GUIスレッドから '_task.Wait()'を呼び出すべきではありません。だから私はあなたがたどったインターネットの例を疑問に思います。 –
ConfigureAwaitf(false)を使用してテストしましたか? –
私は仕事についてmcuhは分かりませんが、あなたはすべての仕事に同じcancelationTokenを使用していませんか? – null