Use local CancellationTokenSource

This commit is contained in:
Malte Rosenbjerg 2025-10-17 22:43:25 +02:00
parent fab7ff0aab
commit 326b3e2719

View file

@ -10,7 +10,6 @@ namespace FFMpegCore;
public class FFMpegArgumentProcessor public class FFMpegArgumentProcessor
{ {
private static readonly Regex ProgressRegex = new(@"time=(\d\d:\d\d:\d\d.\d\d?)", RegexOptions.Compiled); private static readonly Regex ProgressRegex = new(@"time=(\d\d:\d\d:\d\d.\d\d?)", RegexOptions.Compiled);
private readonly CancellationTokenSource _cancellationTokenSource = new();
private readonly List<Action<FFOptions>> _configurations; private readonly List<Action<FFOptions>> _configurations;
private readonly FFMpegArguments _ffMpegArguments; private readonly FFMpegArguments _ffMpegArguments;
private CancellationTokenRegistration? _cancellationTokenRegistration; private CancellationTokenRegistration? _cancellationTokenRegistration;
@ -32,12 +31,6 @@ public class FFMpegArgumentProcessor
private event EventHandler<int> CancelEvent = null!; private event EventHandler<int> CancelEvent = null!;
~FFMpegArgumentProcessor()
{
_cancellationTokenSource.Dispose();
_cancellationTokenRegistration?.Dispose();
}
/// <summary> /// <summary>
/// Register action that will be invoked during the ffmpeg processing, when a progress time is output and parsed and progress percentage is /// Register action that will be invoked during the ffmpeg processing, when a progress time is output and parsed and progress percentage is
/// calculated. /// calculated.
@ -92,6 +85,7 @@ public class FFMpegArgumentProcessor
public FFMpegArgumentProcessor CancellableThrough(CancellationToken token, int timeout = 0) public FFMpegArgumentProcessor CancellableThrough(CancellationToken token, int timeout = 0)
{ {
_cancellationTokenRegistration?.Dispose();
_cancellationTokenRegistration = token.Register(() => Cancel(timeout)); _cancellationTokenRegistration = token.Register(() => Cancel(timeout));
return this; return this;
} }
@ -117,11 +111,12 @@ public class FFMpegArgumentProcessor
{ {
var options = GetConfiguredOptions(ffMpegOptions); var options = GetConfiguredOptions(ffMpegOptions);
var processArguments = PrepareProcessArguments(options); var processArguments = PrepareProcessArguments(options);
using var cancellationTokenSource = new CancellationTokenSource();
IProcessResult? processResult = null; IProcessResult? processResult = null;
try try
{ {
processResult = Process(processArguments).ConfigureAwait(false).GetAwaiter().GetResult(); processResult = Process(processArguments, cancellationTokenSource).ConfigureAwait(false).GetAwaiter().GetResult();
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
@ -138,11 +133,12 @@ public class FFMpegArgumentProcessor
{ {
var options = GetConfiguredOptions(ffMpegOptions); var options = GetConfiguredOptions(ffMpegOptions);
var processArguments = PrepareProcessArguments(options); var processArguments = PrepareProcessArguments(options);
using var cancellationTokenSource = new CancellationTokenSource();
IProcessResult? processResult = null; IProcessResult? processResult = null;
try try
{ {
processResult = await Process(processArguments).ConfigureAwait(false); processResult = await Process(processArguments, cancellationTokenSource).ConfigureAwait(false);
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
@ -155,11 +151,12 @@ public class FFMpegArgumentProcessor
return HandleCompletion(throwOnError, processResult?.ExitCode ?? -1, processResult?.ErrorData ?? Array.Empty<string>()); return HandleCompletion(throwOnError, processResult?.ExitCode ?? -1, processResult?.ErrorData ?? Array.Empty<string>());
} }
private async Task<IProcessResult> Process(ProcessArguments processArguments) private async Task<IProcessResult> Process(ProcessArguments processArguments, CancellationTokenSource cancellationTokenSource)
{ {
IProcessResult processResult = null!; IProcessResult processResult = null!;
if (_cancelled) if (_cancelled)
{ {
_cancellationTokenRegistration?.Dispose();
throw new OperationCanceledException("cancelled before starting processing"); throw new OperationCanceledException("cancelled before starting processing");
} }
@ -171,9 +168,9 @@ public class FFMpegArgumentProcessor
{ {
instance.SendInput("q"); instance.SendInput("q");
if (!_cancellationTokenSource.Token.WaitHandle.WaitOne(timeout, true)) if (!cancellationTokenSource.Token.WaitHandle.WaitOne(timeout, true))
{ {
_cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
instance.Kill(); instance.Kill();
} }
} }
@ -185,12 +182,13 @@ public class FFMpegArgumentProcessor
await Task.WhenAll(instance.WaitForExitAsync().ContinueWith(t => await Task.WhenAll(instance.WaitForExitAsync().ContinueWith(t =>
{ {
processResult = t.Result; processResult = t.Result;
_cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
_ffMpegArguments.Post(); _ffMpegArguments.Post();
}), _ffMpegArguments.During(_cancellationTokenSource.Token)).ConfigureAwait(false); }), _ffMpegArguments.During(cancellationTokenSource.Token)).ConfigureAwait(false);
if (_cancelled) if (_cancelled)
{ {
_cancellationTokenRegistration?.Dispose();
throw new OperationCanceledException("ffmpeg processing was cancelled"); throw new OperationCanceledException("ffmpeg processing was cancelled");
} }
@ -199,6 +197,7 @@ public class FFMpegArgumentProcessor
finally finally
{ {
CancelEvent -= OnCancelEvent; CancelEvent -= OnCancelEvent;
_cancellationTokenRegistration?.Dispose();
} }
} }