diff options
author | Sergey Chebotar <s.chebotar@gmail.com> | 2021-11-11 16:54:02 +0300 |
---|---|---|
committer | Sergey Chebotar <s.chebotar@gmail.com> | 2021-11-11 16:54:02 +0300 |
commit | 475d981364aa18ba22d4d2f78f837d20af4df6a8 (patch) | |
tree | dfbe96d775cd1129a17de33c21c946ba2eeb1d6b /ExcelTaskUtil.cs | |
parent | 3be35e28f6e1c4477772ab74a18cbbdb45046224 (diff) | |
parent | e7d3fe2beae326a2380b4cfed7f33961f40d87ca (diff) |
Merge branch 'dev'
Diffstat (limited to 'ExcelTaskUtil.cs')
-rw-r--r-- | ExcelTaskUtil.cs | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/ExcelTaskUtil.cs b/ExcelTaskUtil.cs new file mode 100644 index 0000000..c7d1b94 --- /dev/null +++ b/ExcelTaskUtil.cs @@ -0,0 +1,133 @@ +using ExcelDna.Integration; +using System.Threading.Tasks; +using System; +using System.Threading; + +namespace Rehau.Sku.Assist +{ + internal static class ExcelTaskUtil + { + public static object Run<TResult>(string callerFunctionName, object callerParameters, Func<CancellationToken, Task<TResult>> taskSource) + { + return ExcelAsyncUtil.Observe(callerFunctionName, callerParameters, delegate + { + var cts = new CancellationTokenSource(); + var task = taskSource(cts.Token); + return new ExcelTaskObservable<TResult>(task, cts); + }); + } + + public static object Run<TResult>(string callerFunctionName, object callerParameters, Func<Task<TResult>> taskSource) + { + return ExcelAsyncUtil.Observe(callerFunctionName, callerParameters, delegate + { + var task = taskSource(); + return new ExcelTaskObservable<TResult>(task); + }); + } + + class ExcelTaskObservable<TResult> : IExcelObservable + { + readonly Task<TResult> _task; + readonly CancellationTokenSource _cts; + public ExcelTaskObservable(Task<TResult> task) + { + _task = task; + } + + public ExcelTaskObservable(Task<TResult> task, CancellationTokenSource cts) + : this(task) + { + _cts = cts; + } + + public IDisposable Subscribe(IExcelObserver observer) + { + switch (_task.Status) + { + case TaskStatus.RanToCompletion: + observer.OnNext(_task.Result); + observer.OnCompleted(); + break; + case TaskStatus.Faulted: + observer.OnError(_task.Exception.InnerException); + break; + case TaskStatus.Canceled: + observer.OnError(new TaskCanceledException(_task)); + break; + default: + _task.ContinueWith(t => + { + switch (t.Status) + { + case TaskStatus.RanToCompletion: + observer.OnNext(t.Result); + observer.OnCompleted(); + break; + case TaskStatus.Faulted: + observer.OnError(t.Exception.InnerException); + break; + case TaskStatus.Canceled: + observer.OnError(new TaskCanceledException(t)); + break; + } + }); + break; + } + + if (_cts != null) + { + return new CancellationDisposable(_cts); + } + + return DefaultDisposable.Instance; + } + } + + sealed class DefaultDisposable : IDisposable + { + + public static readonly DefaultDisposable Instance = new DefaultDisposable(); + + DefaultDisposable() + { + } + + public void Dispose() + { + } + } + + sealed class CancellationDisposable : IDisposable + { + + readonly CancellationTokenSource cts; + public CancellationDisposable(CancellationTokenSource cts) + { + if (cts == null) + { + throw new ArgumentNullException("cts"); + } + + this.cts = cts; + } + + public CancellationDisposable() + : this(new CancellationTokenSource()) + { + } + + public CancellationToken Token + { + get { return cts.Token; } + } + + public void Dispose() + { + cts.Cancel(); + } + } + + } +} + |