mirror of https://github.com/icsharpcode/ILSpy.git
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.
203 lines
7.1 KiB
203 lines
7.1 KiB
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this |
|
// software and associated documentation files (the "Software"), to deal in the Software |
|
// without restriction, including without limitation the rights to use, copy, modify, merge, |
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons |
|
// to whom the Software is furnished to do so, subject to the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be included in all copies or |
|
// substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE |
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
// DEALINGS IN THE SOFTWARE. |
|
|
|
using System; |
|
using System.Threading; |
|
using System.Threading.Tasks; |
|
using ICSharpCode.ILSpy.TextView; |
|
|
|
namespace ICSharpCode.ILSpy |
|
{ |
|
public static class TaskHelper |
|
{ |
|
public static readonly Task CompletedTask = FromResult<object>(null); |
|
|
|
public static Task<T> FromResult<T>(T result) |
|
{ |
|
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>(); |
|
tcs.SetResult(result); |
|
return tcs.Task; |
|
} |
|
|
|
public static Task<T> FromException<T>(Exception ex) |
|
{ |
|
var tcs = new TaskCompletionSource<T>(); |
|
tcs.SetException(ex); |
|
return tcs.Task; |
|
} |
|
|
|
public static Task<T> FromCancellation<T>() |
|
{ |
|
var tcs = new TaskCompletionSource<T>(); |
|
tcs.SetCanceled(); |
|
return tcs.Task; |
|
} |
|
|
|
/// <summary> |
|
/// Sets the result of the TaskCompletionSource based on the result of the finished task. |
|
/// </summary> |
|
public static void SetFromTask<T>(this TaskCompletionSource<T> tcs, Task<T> task) |
|
{ |
|
switch (task.Status) { |
|
case TaskStatus.RanToCompletion: |
|
tcs.SetResult(task.Result); |
|
break; |
|
case TaskStatus.Canceled: |
|
tcs.SetCanceled(); |
|
break; |
|
case TaskStatus.Faulted: |
|
tcs.SetException(task.Exception.InnerExceptions); |
|
break; |
|
default: |
|
throw new InvalidOperationException("The input task must have already finished"); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Sets the result of the TaskCompletionSource based on the result of the finished task. |
|
/// </summary> |
|
public static void SetFromTask(this TaskCompletionSource<object> tcs, Task task) |
|
{ |
|
switch (task.Status) { |
|
case TaskStatus.RanToCompletion: |
|
tcs.SetResult(null); |
|
break; |
|
case TaskStatus.Canceled: |
|
tcs.SetCanceled(); |
|
break; |
|
case TaskStatus.Faulted: |
|
tcs.SetException(task.Exception.InnerExceptions); |
|
break; |
|
default: |
|
throw new InvalidOperationException("The input task must have already finished"); |
|
} |
|
} |
|
|
|
public static Task Then<T>(this Task<T> task, Action<T> action) |
|
{ |
|
if (action == null) |
|
throw new ArgumentNullException(nameof(action)); |
|
return task.ContinueWith(t => action(t.Result), CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()); |
|
} |
|
|
|
public static Task<U> Then<T, U>(this Task<T> task, Func<T, U> func) |
|
{ |
|
if (func == null) |
|
throw new ArgumentNullException(nameof(func)); |
|
return task.ContinueWith(t => func(t.Result), CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()); |
|
} |
|
|
|
public static Task Then<T>(this Task<T> task, Func<T, Task> asyncFunc) |
|
{ |
|
if (asyncFunc == null) |
|
throw new ArgumentNullException(nameof(asyncFunc)); |
|
return task.ContinueWith(t => asyncFunc(t.Result), CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()).Unwrap(); |
|
} |
|
|
|
public static Task<U> Then<T, U>(this Task<T> task, Func<T, Task<U>> asyncFunc) |
|
{ |
|
if (asyncFunc == null) |
|
throw new ArgumentNullException(nameof(asyncFunc)); |
|
return task.ContinueWith(t => asyncFunc(t.Result), CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()).Unwrap(); |
|
} |
|
|
|
public static Task Then(this Task task, Action action) |
|
{ |
|
if (action == null) |
|
throw new ArgumentNullException(nameof(action)); |
|
return task.ContinueWith(t => { |
|
t.Wait(); |
|
action(); |
|
}, CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()); |
|
} |
|
|
|
public static Task<U> Then<U>(this Task task, Func<U> func) |
|
{ |
|
if (func == null) |
|
throw new ArgumentNullException(nameof(func)); |
|
return task.ContinueWith(t => { |
|
t.Wait(); |
|
return func(); |
|
}, CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()); |
|
} |
|
|
|
public static Task Then(this Task task, Func<Task> asyncAction) |
|
{ |
|
if (asyncAction == null) |
|
throw new ArgumentNullException(nameof(asyncAction)); |
|
return task.ContinueWith(t => { |
|
t.Wait(); |
|
return asyncAction(); |
|
}, CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()).Unwrap(); |
|
} |
|
|
|
public static Task<U> Then<U>(this Task task, Func<Task<U>> asyncFunc) |
|
{ |
|
if (asyncFunc == null) |
|
throw new ArgumentNullException(nameof(asyncFunc)); |
|
return task.ContinueWith(t => { |
|
t.Wait(); |
|
return asyncFunc(); |
|
}, CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()).Unwrap(); |
|
} |
|
|
|
/// <summary> |
|
/// If the input task fails, calls the action to handle the error. |
|
/// </summary> |
|
/// <returns> |
|
/// Returns a task that finishes successfully when error handling has completed. |
|
/// If the input task ran successfully, the returned task completes successfully. |
|
/// If the input task was cancelled, the returned task is cancelled as well. |
|
/// </returns> |
|
public static Task Catch<TException>(this Task task, Action<TException> action) where TException : Exception |
|
{ |
|
if (action == null) |
|
throw new ArgumentNullException(nameof(action)); |
|
return task.ContinueWith(t => { |
|
if (t.IsFaulted) { |
|
Exception ex = t.Exception; |
|
while (ex is AggregateException) |
|
ex = ex.InnerException; |
|
if (ex is TException) |
|
action((TException)ex); |
|
else |
|
throw t.Exception; |
|
} |
|
}, CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()); |
|
} |
|
|
|
/// <summary> |
|
/// Ignore exceptions thrown by the task. |
|
/// </summary> |
|
public static void IgnoreExceptions(this Task task) |
|
{ |
|
} |
|
|
|
/// <summary> |
|
/// Handle exceptions by displaying the error message in the text view. |
|
/// </summary> |
|
public static void HandleExceptions(this Task task) |
|
{ |
|
task.Catch<Exception>(exception => MainWindow.Instance.Dispatcher.BeginInvoke(new Action(delegate { |
|
AvalonEditTextOutput output = new AvalonEditTextOutput(); |
|
output.Write(exception.ToString()); |
|
MainWindow.Instance.TextView.ShowText(output); |
|
}))).IgnoreExceptions(); |
|
} |
|
} |
|
}
|
|
|