Skip to content

Commit 92fd623

Browse files
Merge branch 'v8/8.8' into v8/8.9
2 parents 58c6e65 + 02d6011 commit 92fd623

File tree

8 files changed

+79
-11
lines changed

8 files changed

+79
-11
lines changed

src/Umbraco.Core/Logging/LoggingTaskExtension.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Threading;
23
using System.Threading.Tasks;
34

45
namespace Umbraco.Core.Logging
@@ -14,7 +15,12 @@ internal static class LoggingTaskExtension
1415
/// </summary>
1516
public static Task LogErrors(this Task task, Action<string, Exception> logMethod)
1617
{
17-
return task.ContinueWith(t => LogErrorsInner(t, logMethod), TaskContinuationOptions.OnlyOnFaulted);
18+
return task.ContinueWith(
19+
t => LogErrorsInner(t, logMethod),
20+
CancellationToken.None,
21+
TaskContinuationOptions.OnlyOnFaulted,
22+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
23+
TaskScheduler.Default);
1824
}
1925

2026
/// <summary>
@@ -26,7 +32,10 @@ public static Task LogErrors(this Task task, Action<string, Exception> logMethod
2632
/// </summary>
2733
public static Task LogErrorsWaitable(this Task task, Action<string, Exception> logMethod)
2834
{
29-
return task.ContinueWith(t => LogErrorsInner(t, logMethod));
35+
return task.ContinueWith(
36+
t => LogErrorsInner(t, logMethod),
37+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
38+
TaskScheduler.Default);
3039
}
3140

3241
private static void LogErrorsInner(Task task, Action<string, Exception> logAction)

src/Umbraco.Core/Runtime/MainDom.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Security.Cryptography;
55
using System.Threading;
6+
using System.Threading.Tasks;
67
using System.Web.Hosting;
78
using Umbraco.Core;
89
using Umbraco.Core.Logging;
@@ -38,6 +39,9 @@ internal class MainDom : IMainDom, IRegisteredObject, IDisposable
3839

3940
private const int LockTimeoutMilliseconds = 40000; // 40 seconds
4041

42+
private Task _listenTask;
43+
private Task _listenCompleteTask;
44+
4145
#endregion
4246

4347
#region Ctor
@@ -172,7 +176,13 @@ private bool Acquire()
172176
try
173177
{
174178
// Listen for the signal from another AppDomain coming online to release the lock
175-
_mainDomLock.ListenAsync().ContinueWith(_ => OnSignal("signal"));
179+
_listenTask = _mainDomLock.ListenAsync();
180+
_listenCompleteTask = _listenTask.ContinueWith(t =>
181+
{
182+
_logger.Debug<MainDom>("Listening task completed with {TaskStatus}", _listenTask.Status);
183+
184+
OnSignal("signal");
185+
}, TaskScheduler.Default); // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
176186
}
177187
catch (OperationCanceledException ex)
178188
{

src/Umbraco.Core/Runtime/SqlMainDomLock.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,12 @@ public Task ListenAsync()
125125

126126
// Create a long running task (dedicated thread)
127127
// to poll to check if we are still the MainDom registered in the DB
128-
return Task.Factory.StartNew(ListeningLoop, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
128+
return Task.Factory.StartNew(
129+
ListeningLoop,
130+
_cancellationTokenSource.Token,
131+
TaskCreationOptions.LongRunning,
132+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
133+
TaskScheduler.Default);
129134

130135
}
131136

@@ -166,7 +171,11 @@ private void ListeningLoop()
166171
// the other MainDom is taking to startup. In this case the db row will just be deleted and the
167172
// new MainDom will just take over.
168173
if (_cancellationTokenSource.IsCancellationRequested)
174+
{
175+
_logger.Debug<SqlMainDomLock>("Task canceled, exiting loop");
169176
return;
177+
}
178+
170179
IUmbracoDatabase db = null;
171180
try
172181
{
@@ -190,8 +199,10 @@ private void ListeningLoop()
190199
// We need to keep on listening unless we've been notified by our own AppDomain to shutdown since
191200
// we don't want to shutdown resources controlled by MainDom inadvertently. We'll just keep listening otherwise.
192201
if (_cancellationTokenSource.IsCancellationRequested)
202+
{
203+
_logger.Debug<SqlMainDomLock>("Task canceled, exiting loop");
193204
return;
194-
205+
}
195206
}
196207
finally
197208
{
@@ -396,6 +407,8 @@ protected virtual void Dispose(bool disposing)
396407
{
397408
lock (_locker)
398409
{
410+
_logger.Debug<SqlMainDomLock>($"{nameof(SqlMainDomLock)} Disposing...");
411+
399412
// immediately cancel all sub-tasks, we don't want them to keep querying
400413
_cancellationTokenSource.Cancel();
401414
_cancellationTokenSource.Dispose();

src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1380,7 +1380,11 @@ private Task CollectAsyncLocked()
13801380
{
13811381
_collectTask = null;
13821382
}
1383-
}, TaskContinuationOptions.ExecuteSynchronously);
1383+
},
1384+
CancellationToken.None,
1385+
TaskContinuationOptions.ExecuteSynchronously,
1386+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
1387+
TaskScheduler.Default);
13841388
// ReSharper restore InconsistentlySynchronizedField
13851389

13861390
return task;

src/Umbraco.Web/PublishedCache/NuCache/SnapDictionary.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,11 @@ private Task CollectAsyncLocked()
380380
{
381381
_collectTask = null;
382382
}
383-
}, TaskContinuationOptions.ExecuteSynchronously);
383+
},
384+
CancellationToken.None,
385+
TaskContinuationOptions.ExecuteSynchronously,
386+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
387+
TaskScheduler.Default);
384388
// ReSharper restore InconsistentlySynchronizedField
385389

386390
return task;

src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,9 +756,17 @@ private void StopInitial()
756756
lock (_locker)
757757
{
758758
if (_runningTask != null)
759-
_runningTask.ContinueWith(_ => StopImmediate());
759+
{
760+
_runningTask.ContinueWith(
761+
_ => StopImmediate(),
762+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
763+
TaskScheduler.Default);
764+
}
760765
else
766+
{
761767
StopImmediate();
768+
}
769+
762770
}
763771
}
764772

src/Umbraco.Web/Scheduling/TaskAndFactoryExtensions.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ internal static class TaskAndFactoryExtensions
88
{
99
#region Task Extensions
1010

11+
// TODO: Not used, is this used in Deploy or something?
1112
static void SetCompletionSource<TResult>(TaskCompletionSource<TResult> completionSource, Task task)
1213
{
1314
if (task.IsFaulted)
@@ -16,6 +17,7 @@ static void SetCompletionSource<TResult>(TaskCompletionSource<TResult> completio
1617
completionSource.SetResult(default(TResult));
1718
}
1819

20+
// TODO: Not used, is this used in Deploy or something?
1921
static void SetCompletionSource<TResult>(TaskCompletionSource<TResult> completionSource, Task<TResult> task)
2022
{
2123
if (task.IsFaulted)
@@ -24,17 +26,33 @@ static void SetCompletionSource<TResult>(TaskCompletionSource<TResult> completio
2426
completionSource.SetResult(task.Result);
2527
}
2628

29+
// TODO: Not used, is this used in Deploy or something?
2730
public static Task ContinueWithTask(this Task task, Func<Task, Task> continuation)
2831
{
2932
var completionSource = new TaskCompletionSource<object>();
30-
task.ContinueWith(atask => continuation(atask).ContinueWith(atask2 => SetCompletionSource(completionSource, atask2)));
33+
task.ContinueWith(atask => continuation(atask).ContinueWith(
34+
atask2 => SetCompletionSource(completionSource, atask2),
35+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
36+
TaskScheduler.Default),
37+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
38+
TaskScheduler.Default);
3139
return completionSource.Task;
3240
}
3341

42+
// TODO: Not used, is this used in Deploy or something?
3443
public static Task ContinueWithTask(this Task task, Func<Task, Task> continuation, CancellationToken token)
3544
{
3645
var completionSource = new TaskCompletionSource<object>();
37-
task.ContinueWith(atask => continuation(atask).ContinueWith(atask2 => SetCompletionSource(completionSource, atask2), token), token);
46+
task.ContinueWith(atask => continuation(atask).ContinueWith(
47+
atask2 => SetCompletionSource(completionSource, atask2),
48+
token,
49+
TaskContinuationOptions.None,
50+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
51+
TaskScheduler.Default),
52+
token,
53+
TaskContinuationOptions.None,
54+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
55+
TaskScheduler.Default);
3856
return completionSource.Task;
3957
}
4058

src/Umbraco.Web/WebApi/HttpActionContextExtensions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ public static MultipartFormDataStreamProvider ReadAsMultipart(this HttpActionCon
8989
throw x.Exception;
9090
}
9191
result = x.ConfigureAwait(false).GetAwaiter().GetResult();
92-
});
92+
},
93+
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
94+
TaskScheduler.Default);
9395
task.Wait();
9496

9597
if (result == null)

0 commit comments

Comments
 (0)