Updates BackgroundTaskRunner to support async operations. Updates the content xml cache file persisting to use a IBackgroundTask instead of the strange queuing for persistence - which was super strange because in many cases another request thread will actually be the thread that is persisting the xml file than the request thread that requested it created. This implementation is far better, the xml file will be persisted on a non request thread and will handle multiple documents being published at the same time guaranteeing that the latest published version is the one persisted. The file persistence is also web aware (due to how BackgroundTaskRunner works) so during app shutdown the file will still be written if it's currently being processed.

This commit is contained in:
Shannon
2015-01-29 12:45:44 +11:00
parent e775471013
commit a82035061c
12 changed files with 227 additions and 169 deletions

View File

@@ -146,7 +146,8 @@ namespace Umbraco.Web.Scheduling
T remainingTask;
while (_tasks.TryTake(out remainingTask))
{
ConsumeTaskInternal(remainingTask);
ConsumeTaskInternalAsync(remainingTask)
.Wait(); //block until it completes
}
}
@@ -178,7 +179,7 @@ namespace Umbraco.Web.Scheduling
var token = _tokenSource.Token;
_consumer = Task.Factory.StartNew(() =>
StartThread(token),
StartThreadAsync(token),
token,
_dedicatedThread ? TaskCreationOptions.LongRunning : TaskCreationOptions.None,
TaskScheduler.Default);
@@ -197,7 +198,7 @@ namespace Umbraco.Web.Scheduling
/// Invokes a new worker thread to consume tasks
/// </summary>
/// <param name="token"></param>
private void StartThread(CancellationToken token)
private async Task StartThreadAsync(CancellationToken token)
{
// Was cancellation already requested?
if (token.IsCancellationRequested)
@@ -206,14 +207,14 @@ namespace Umbraco.Web.Scheduling
token.ThrowIfCancellationRequested();
}
TakeAndConsumeTask(token);
await TakeAndConsumeTaskAsync(token);
}
/// <summary>
/// Trys to get a task from the queue, if there isn't one it will wait a second and try again
/// </summary>
/// <param name="token"></param>
private void TakeAndConsumeTask(CancellationToken token)
private async Task TakeAndConsumeTaskAsync(CancellationToken token)
{
if (token.IsCancellationRequested)
{
@@ -235,25 +236,25 @@ namespace Umbraco.Web.Scheduling
// cancel when we shutdown
foreach (var t in _tasks.GetConsumingEnumerable(token))
{
ConsumeTaskCancellable(t, token);
await ConsumeTaskCancellableAsync(t, token);
}
//recurse and keep going
TakeAndConsumeTask(token);
await TakeAndConsumeTaskAsync(token);
}
else
{
T repositoryTask;
while (_tasks.TryTake(out repositoryTask))
{
ConsumeTaskCancellable(repositoryTask, token);
await ConsumeTaskCancellableAsync(repositoryTask, token);
}
//the task will end here
}
}
internal void ConsumeTaskCancellable(T task, CancellationToken token)
internal async Task ConsumeTaskCancellableAsync(T task, CancellationToken token)
{
if (token.IsCancellationRequested)
{
@@ -266,10 +267,10 @@ namespace Umbraco.Web.Scheduling
token.ThrowIfCancellationRequested();
}
ConsumeTaskInternal(task);
await ConsumeTaskInternalAsync(task);
}
private void ConsumeTaskInternal(T task)
private async Task ConsumeTaskInternalAsync(T task)
{
try
{
@@ -279,7 +280,14 @@ namespace Umbraco.Web.Scheduling
{
using (task)
{
task.Run();
if (task.IsAsync)
{
await task.RunAsync();
}
else
{
task.Run();
}
}
}
catch (Exception e)