Skip to content

Commit 14a4ce6

Browse files
authored
Add cancellationtoken to timeout tasks (#1380)
1 parent 37ea569 commit 14a4ce6

File tree

3 files changed

+38
-15
lines changed

3 files changed

+38
-15
lines changed

lib/PuppeteerSharp/ChromiumProcess.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -609,11 +609,14 @@ public Task EnterFromAsync(ChromiumProcess p, State fromState, TimeSpan timeout)
609609
public override async Task ExitAsync(ChromiumProcess p, TimeSpan timeout)
610610
{
611611
var waitForExitTask = WaitForExitAsync(p);
612-
await waitForExitTask.WithTimeout(async () =>
613-
{
614-
await Killing.EnterFromAsync(p, this).ConfigureAwait(false);
615-
await waitForExitTask.ConfigureAwait(false);
616-
}, timeout).ConfigureAwait(false);
612+
await waitForExitTask.WithTimeout(
613+
async () =>
614+
{
615+
await Killing.EnterFromAsync(p, this).ConfigureAwait(false);
616+
await waitForExitTask.ConfigureAwait(false);
617+
},
618+
timeout,
619+
CancellationToken.None).ConfigureAwait(false);
617620
}
618621

619622
public override Task KillAsync(ChromiumProcess p) => Killing.EnterFromAsync(p, this);

lib/PuppeteerSharp/Helpers/TaskHelper.cs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,13 @@ public static class TaskHelper
2020
/// <param name="task">Task to wait for.</param>
2121
/// <param name="milliseconds">Milliseconds timeout.</param>
2222
/// <param name="exceptionFactory">Optional timeout exception factory.</param>
23-
public static Task WithTimeout(this Task task, int milliseconds = 1_000, Func<TimeSpan, Exception> exceptionFactory = null)
24-
=> WithTimeout(task, TimeSpan.FromMilliseconds(milliseconds), exceptionFactory);
23+
/// <param name="cancellationToken">Cancellation token.</param>
24+
public static Task WithTimeout(
25+
this Task task,
26+
int milliseconds = 1_000,
27+
Func<TimeSpan, Exception> exceptionFactory = null,
28+
CancellationToken cancellationToken = default)
29+
=> WithTimeout(task, TimeSpan.FromMilliseconds(milliseconds), exceptionFactory, cancellationToken);
2530

2631
//Recipe from https://blogs.msdn.microsoft.com/pfxteam/2012/10/05/how-do-i-cancel-non-cancelable-async-operations/
2732
/// <summary>
@@ -31,10 +36,16 @@ public static Task WithTimeout(this Task task, int milliseconds = 1_000, Func<Ti
3136
/// <param name="task">Task to wait for.</param>
3237
/// <param name="timeout">The timeout period.</param>
3338
/// <param name="exceptionFactory">Optional timeout exception factory.</param>
34-
public static Task WithTimeout(this Task task, TimeSpan timeout, Func<TimeSpan, Exception> exceptionFactory = null)
39+
/// <param name="cancellationToken">Cancellation token.</param>
40+
public static Task WithTimeout(
41+
this Task task,
42+
TimeSpan timeout,
43+
Func<TimeSpan, Exception> exceptionFactory = null,
44+
CancellationToken cancellationToken = default)
3545
=> task.WithTimeout(
3646
() => throw (exceptionFactory ?? DefaultExceptionFactory)(timeout),
37-
timeout);
47+
timeout,
48+
cancellationToken);
3849

3950
//Recipe from https://blogs.msdn.microsoft.com/pfxteam/2012/10/05/how-do-i-cancel-non-cancelable-async-operations/
4051
/// <summary>
@@ -44,8 +55,13 @@ public static Task WithTimeout(this Task task, TimeSpan timeout, Func<TimeSpan,
4455
/// <param name="task">Task to wait for.</param>
4556
/// <param name="timeoutAction">Action to be executed on Timeout.</param>
4657
/// <param name="milliseconds">Milliseconds timeout.</param>
47-
public static Task WithTimeout(this Task task, Func<Task> timeoutAction, int milliseconds = 1_000)
48-
=> WithTimeout(task, timeoutAction, TimeSpan.FromMilliseconds(milliseconds));
58+
/// <param name="cancellationToken">Cancellation token.</param>
59+
public static Task WithTimeout(
60+
this Task task,
61+
Func<Task> timeoutAction,
62+
int milliseconds = 1_000,
63+
CancellationToken cancellationToken = default)
64+
=> WithTimeout(task, timeoutAction, TimeSpan.FromMilliseconds(milliseconds), cancellationToken);
4965

5066
//Recipe from https://blogs.msdn.microsoft.com/pfxteam/2012/10/05/how-do-i-cancel-non-cancelable-async-operations/
5167
/// <summary>
@@ -55,9 +71,10 @@ public static Task WithTimeout(this Task task, Func<Task> timeoutAction, int mil
5571
/// <param name="task">Task to wait for.</param>
5672
/// <param name="timeoutAction">Action to be executed on Timeout.</param>
5773
/// <param name="timeout">The timeout period.</param>
58-
public static async Task WithTimeout(this Task task, Func<Task> timeoutAction, TimeSpan timeout)
74+
/// <param name="cancellationToken">Cancellation token.</param>
75+
public static async Task WithTimeout(this Task task, Func<Task> timeoutAction, TimeSpan timeout, CancellationToken cancellationToken)
5976
{
60-
if (await TimeoutTask(task, timeout).ConfigureAwait(false))
77+
if (await TimeoutTask(task, timeout).ConfigureAwait(false) && !cancellationToken.IsCancellationRequested)
6178
{
6279
await timeoutAction().ConfigureAwait(false);
6380
}

lib/PuppeteerSharp/LifecycleWatcher.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Linq;
55
using System.Diagnostics.Contracts;
66
using PuppeteerSharp.Helpers;
7+
using System.Threading;
78

89
namespace PuppeteerSharp
910
{
@@ -31,6 +32,7 @@ internal class LifecycleWatcher : IDisposable
3132
private TaskCompletionSource<bool> _sameDocumentNavigationTaskWrapper;
3233
private TaskCompletionSource<bool> _lifecycleTaskWrapper;
3334
private TaskCompletionSource<bool> _terminationTaskWrapper;
35+
private CancellationTokenSource _terminationCancellationToken;
3436

3537
public LifecycleWatcher(
3638
FrameManager frameManager,
@@ -55,6 +57,7 @@ public LifecycleWatcher(
5557
_newDocumentNavigationTaskWrapper = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
5658
_lifecycleTaskWrapper = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
5759
_terminationTaskWrapper = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
60+
_terminationCancellationToken = new CancellationTokenSource();
5861

5962
frameManager.LifecycleEvent += FrameManager_LifecycleEvent;
6063
frameManager.FrameNavigatedWithinDocument += NavigatedWithinDocument;
@@ -70,8 +73,7 @@ public LifecycleWatcher(
7073
public Task<bool> SameDocumentNavigationTask => _sameDocumentNavigationTaskWrapper.Task;
7174
public Task<bool> NewDocumentNavigationTask => _newDocumentNavigationTaskWrapper.Task;
7275
public Response NavigationResponse => _navigationRequest?.Response;
73-
public Task TimeoutOrTerminationTask
74-
=> _terminationTaskWrapper.Task.WithTimeout(_timeout);
76+
public Task TimeoutOrTerminationTask => _terminationTaskWrapper.Task.WithTimeout(_timeout, cancellationToken: _terminationCancellationToken.Token);
7577
public Task LifecycleTask => _lifecycleTaskWrapper.Task;
7678

7779
#endregion
@@ -168,6 +170,7 @@ public void Dispose(bool disposing)
168170
_frameManager.FrameDetached -= OnFrameDetached;
169171
_frameManager.NetworkManager.Request -= OnRequest;
170172
_frameManager.Client.Disconnected -= OnClientDisconnected;
173+
_terminationCancellationToken.Cancel();
171174
}
172175

173176
#endregion

0 commit comments

Comments
 (0)