You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.6 KiB
100 lines
2.6 KiB
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) |
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) |
|
|
|
using System; |
|
using System.Windows.Threading; |
|
|
|
namespace ICSharpCode.Profiler.Controls |
|
{ |
|
class SingleTask { |
|
Task currentTask; |
|
Dispatcher dispatcher; |
|
|
|
public SingleTask(Dispatcher dispatcher) |
|
{ |
|
if (dispatcher == null) |
|
throw new ArgumentNullException("dispatcher"); |
|
this.dispatcher = dispatcher; |
|
this.currentTask = null; |
|
} |
|
|
|
// task = local reference to the task instance of the current thread |
|
// currentUpdateTask = reference to the currently executed task |
|
// |
|
// Consider two tasks 1 and 2 running in parallel: |
|
// |
|
// These are the only two possible execution orders for two parallel updates. |
|
// Update and Complete cannot execute in parallel because they both run on the UI Thread |
|
// |
|
// Update(1) |
|
// currentUpdateTask = 1 |
|
// Update(2) |
|
// currentUpdateTask = 2 |
|
// Complete(1) |
|
// currentUpdateTask = 2 |
|
// Complete(2) |
|
// currentUpdateTask = null |
|
// |
|
// Update(1) |
|
// currentUpdateTask = 1 |
|
// Update(2) |
|
// currentUpdateTask = 2 |
|
// Complete(2) |
|
// currentUpdateTask = null |
|
// Complete(1) |
|
// currentUpdateTask = null |
|
|
|
public void Cancel() |
|
{ |
|
dispatcher.VerifyAccess(); |
|
|
|
if (currentTask != null) { |
|
currentTask.Cancel(); |
|
currentTask = null; |
|
} |
|
} |
|
|
|
public void Execute(Action backgroundAction, Action completionAction, Action failedAction) |
|
{ |
|
if (backgroundAction == null) |
|
throw new ArgumentNullException("backgroundAction"); |
|
|
|
Cancel(); |
|
|
|
Task task = Task.Start(backgroundAction); |
|
currentTask = task; |
|
currentTask.RunWhenComplete( |
|
dispatcher, |
|
() => { |
|
// do not use task.IsCancelled because we do not |
|
// want to raise completionAction if the task |
|
// was successfully completed but another task |
|
// was started before we received the completion callback. |
|
if (currentTask == task) { |
|
currentTask = null; |
|
if (completionAction != null) |
|
completionAction(); |
|
} else { |
|
if (failedAction != null) |
|
failedAction(); |
|
} |
|
} |
|
); |
|
} |
|
|
|
public void Execute<T>(Func<T> backgroundAction, Action<T> completionAction, Action failedAction) |
|
{ |
|
if (backgroundAction == null) |
|
throw new ArgumentNullException("backgroundAction"); |
|
if (completionAction == null) |
|
throw new ArgumentNullException("completionAction"); |
|
|
|
T returnValue = default(T); |
|
Execute(delegate { returnValue = backgroundAction(); }, |
|
delegate { completionAction(returnValue); }, |
|
failedAction |
|
); |
|
} |
|
} |
|
|
|
}
|
|
|