forked from readyplayerme/rpm-unity-sdk-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOperationExecutor.cs
71 lines (60 loc) · 2.03 KB
/
OperationExecutor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ReadyPlayerMe.Core
{
public class OperationExecutor<T> where T : Context
{
private readonly IOperation<T>[] operations;
private readonly int operationsCount;
public int Timeout;
public Action<IOperation<T>> OperationCompleted;
private CancellationTokenSource ctxSource;
private int currentIndex;
private float currentProgress;
public OperationExecutor(IOperation<T>[] operations)
{
this.operations = operations;
operationsCount = operations.Length;
}
public bool IsCancelled => ctxSource.IsCancellationRequested;
public event Action<float, string> ProgressChanged;
public async Task<T> Execute(T context)
{
ctxSource = new CancellationTokenSource();
foreach (IOperation<T> operation in operations)
{
operation.ProgressChanged += OnProgressChanged;
operation.Timeout = Timeout;
try
{
context = await operation.Execute(context, ctxSource.Token);
currentIndex++;
}
catch
{
if (ctxSource.IsCancellationRequested)
{
ctxSource.Dispose();
}
throw;
}
operation.ProgressChanged -= OnProgressChanged;
OperationCompleted?.Invoke(operation);
}
return context;
}
public void Cancel()
{
if (!ctxSource.IsCancellationRequested)
{
ctxSource?.Cancel();
}
}
private void OnProgressChanged(float progress)
{
currentProgress = 1f / operationsCount * (currentIndex + progress);
ProgressChanged?.Invoke(currentProgress, operations[currentIndex].GetType().Name);
}
}
}