public ActiveTask( int id, TaskRunnerFactoryDelegate factory, Action <object?> progressUpdate, Task?previous, Action onComplete) { if (factory is null) { throw new ArgumentNullException(nameof(factory)); } var canceller = new CancellationTokenSource(); // Need to guarantee deferred operation to prevent weird state issues. Task = Task.Run(() => previous == null ? factory(id, canceller.Token, progressUpdate) : previous.ContinueWith(t => factory(id, canceller.Token, progressUpdate), TaskContinuationOptions.ExecuteSynchronously)) .ContinueWith(t => { onComplete(); return(t); }, TaskContinuationOptions.ExecuteSynchronously) .Unwrap(); Task.ContinueWith(t => Dispose()); _canceller = canceller; }
public ValueTask <ITaskRunner> Create(TaskRunnerFactoryDelegate factory) { var registry = Registry; var id = Interlocked.Increment(ref LatestId); var runner = new TaskRunner(id, factory, Logger); if (!Registry.TryAdd(id, runner)) { throw new Exception($"Id ({id}) already exists"); // should never happen, but lets cover this case. } runner.ProgressUpdated.Subscribe(progress => SignalProgressUpdated(id, progress)); runner.StateUpdated.Subscribe(state => SignalStateUpdated(id, state)); Log("created", runner.Id); return(new ValueTask <ITaskRunner>(runner)); }
public TaskRunnerFactory(ITaskRunnerRegistryService registry, TaskRunnerFactoryDelegate factory) { Registry = registry ?? throw new ArgumentNullException(nameof(registry)); Factory = factory ?? throw new ArgumentNullException(nameof(factory)); }
public TaskRunner(int id, TaskRunnerFactoryDelegate factory, ILogger logger) : this(id, logger) { Factory = factory ?? throw new ArgumentNullException(nameof(factory)); StateSubject.Init(TaskRunnerState.Stopped); ProgressSubject.Init(default);