mirror of
https://github.com/rosenbjerg/FFMpegCore.git
synced 2025-12-14 01:55:45 +00:00
Improve cancellation handling
This commit is contained in:
parent
fc5e8a66e3
commit
e01b73787d
1 changed files with 34 additions and 17 deletions
|
|
@ -10,8 +10,11 @@ namespace FFMpegCore;
|
|||
public class FFMpegArgumentProcessor
|
||||
{
|
||||
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 FFMpegArguments _ffMpegArguments;
|
||||
private CancellationTokenRegistration? _cancellationTokenRegistration;
|
||||
private bool _cancelled;
|
||||
private FFMpegLogLevel? _logLevel;
|
||||
private Action<string>? _onError;
|
||||
private Action<string>? _onOutput;
|
||||
|
|
@ -29,6 +32,12 @@ public class FFMpegArgumentProcessor
|
|||
|
||||
private event EventHandler<int> CancelEvent = null!;
|
||||
|
||||
~FFMpegArgumentProcessor()
|
||||
{
|
||||
_cancellationTokenSource.Dispose();
|
||||
_cancellationTokenRegistration?.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register action that will be invoked during the ffmpeg processing, when a progress time is output and parsed and progress percentage is
|
||||
/// calculated.
|
||||
|
|
@ -71,13 +80,21 @@ public class FFMpegArgumentProcessor
|
|||
|
||||
public FFMpegArgumentProcessor CancellableThrough(out Action cancel, int timeout = 0)
|
||||
{
|
||||
cancel = () => CancelEvent?.Invoke(this, timeout);
|
||||
cancel = () =>
|
||||
{
|
||||
_cancelled = true;
|
||||
CancelEvent?.Invoke(this, timeout);
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
public FFMpegArgumentProcessor CancellableThrough(CancellationToken token, int timeout = 0)
|
||||
{
|
||||
token.Register(() => CancelEvent?.Invoke(this, timeout));
|
||||
_cancellationTokenRegistration = token.Register(() =>
|
||||
{
|
||||
_cancelled = true;
|
||||
CancelEvent?.Invoke(this, timeout);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -101,12 +118,12 @@ public class FFMpegArgumentProcessor
|
|||
public bool ProcessSynchronously(bool throwOnError = true, FFOptions? ffMpegOptions = null)
|
||||
{
|
||||
var options = GetConfiguredOptions(ffMpegOptions);
|
||||
var processArguments = PrepareProcessArguments(options, out var cancellationTokenSource);
|
||||
var processArguments = PrepareProcessArguments(options);
|
||||
|
||||
IProcessResult? processResult = null;
|
||||
try
|
||||
{
|
||||
processResult = Process(processArguments, cancellationTokenSource).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
processResult = Process(processArguments).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
|
@ -122,12 +139,12 @@ public class FFMpegArgumentProcessor
|
|||
public async Task<bool> ProcessAsynchronously(bool throwOnError = true, FFOptions? ffMpegOptions = null)
|
||||
{
|
||||
var options = GetConfiguredOptions(ffMpegOptions);
|
||||
var processArguments = PrepareProcessArguments(options, out var cancellationTokenSource);
|
||||
var processArguments = PrepareProcessArguments(options);
|
||||
|
||||
IProcessResult? processResult = null;
|
||||
try
|
||||
{
|
||||
processResult = await Process(processArguments, cancellationTokenSource).ConfigureAwait(false);
|
||||
processResult = await Process(processArguments).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
|
@ -140,23 +157,25 @@ public class FFMpegArgumentProcessor
|
|||
return HandleCompletion(throwOnError, processResult?.ExitCode ?? -1, processResult?.ErrorData ?? Array.Empty<string>());
|
||||
}
|
||||
|
||||
private async Task<IProcessResult> Process(ProcessArguments processArguments, CancellationTokenSource cancellationTokenSource)
|
||||
private async Task<IProcessResult> Process(ProcessArguments processArguments)
|
||||
{
|
||||
IProcessResult processResult = null!;
|
||||
if (_cancelled)
|
||||
{
|
||||
throw new OperationCanceledException("cancelled before starting processing");
|
||||
}
|
||||
|
||||
_ffMpegArguments.Pre();
|
||||
|
||||
using var instance = processArguments.Start();
|
||||
var cancelled = false;
|
||||
|
||||
void OnCancelEvent(object sender, int timeout)
|
||||
{
|
||||
cancelled = true;
|
||||
instance.SendInput("q");
|
||||
|
||||
if (!cancellationTokenSource.Token.WaitHandle.WaitOne(timeout, true))
|
||||
if (!_cancellationTokenSource.Token.WaitHandle.WaitOne(timeout, true))
|
||||
{
|
||||
cancellationTokenSource.Cancel();
|
||||
_cancellationTokenSource.Cancel();
|
||||
instance.Kill();
|
||||
}
|
||||
}
|
||||
|
|
@ -168,11 +187,11 @@ public class FFMpegArgumentProcessor
|
|||
await Task.WhenAll(instance.WaitForExitAsync().ContinueWith(t =>
|
||||
{
|
||||
processResult = t.Result;
|
||||
cancellationTokenSource.Cancel();
|
||||
_cancellationTokenSource.Cancel();
|
||||
_ffMpegArguments.Post();
|
||||
}), _ffMpegArguments.During(cancellationTokenSource.Token)).ConfigureAwait(false);
|
||||
}), _ffMpegArguments.During(_cancellationTokenSource.Token)).ConfigureAwait(false);
|
||||
|
||||
if (cancelled)
|
||||
if (_cancelled)
|
||||
{
|
||||
throw new OperationCanceledException("ffmpeg processing was cancelled");
|
||||
}
|
||||
|
|
@ -214,8 +233,7 @@ public class FFMpegArgumentProcessor
|
|||
return options;
|
||||
}
|
||||
|
||||
private ProcessArguments PrepareProcessArguments(FFOptions ffOptions,
|
||||
out CancellationTokenSource cancellationTokenSource)
|
||||
private ProcessArguments PrepareProcessArguments(FFOptions ffOptions)
|
||||
{
|
||||
FFMpegHelper.RootExceptionCheck();
|
||||
FFMpegHelper.VerifyFFMpegExists(ffOptions);
|
||||
|
|
@ -245,7 +263,6 @@ public class FFMpegArgumentProcessor
|
|||
WorkingDirectory = ffOptions.WorkingDirectory
|
||||
};
|
||||
var processArguments = new ProcessArguments(startInfo);
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
if (_onOutput != null)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue