aboutsummaryrefslogtreecommitdiff
path: root/ExcelTaskUtil.cs
diff options
context:
space:
mode:
authorSergey Chebotar <s.chebotar@gmail.com>2021-11-11 16:33:40 +0300
committerSergey Chebotar <s.chebotar@gmail.com>2021-11-11 16:33:40 +0300
commite7d3fe2beae326a2380b4cfed7f33961f40d87ca (patch)
tree8da936709596912823ebbca2790c725fd50d434e /ExcelTaskUtil.cs
Init commit
Diffstat (limited to 'ExcelTaskUtil.cs')
-rw-r--r--ExcelTaskUtil.cs133
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();
+ }
+ }
+
+ }
+}
+