private IEnumerator WhenAnyで何か1つのタスクが終わるのを待てるIterator() { var delays = new[] { 3, 5, 7, 9, 11, 13 }; var tasks = delays.Select(d => Task.Run(() => Coroutines.NFrame(d))).ToArray(); while (true) { var task = Task.WhenAny(tasks); yield return task; var first = task.Result; // delays が昇順で並んでいるので、前のタスクから終わるはず Assert.AreEqual(first, tasks[0]); // delays に同じ値を入れていないので、同時に1個ずつしか終わらないはず foreach (var t in tasks.Skip(1)) { Assert.IsFalse(t.IsCompleted); } // 終わったやつを除外。全部終わったら終了 tasks = tasks.Where(t => t != first).ToArray(); if (tasks.Length == 0) break; } }
static System.Collections.IEnumerator 進捗報告付きのコルーチン(Action<int> completed, IteratorTasks.IProgress<int> progress) { for (int i = 0; i < 100; i++) { progress.Report(i); yield return null; } completed(100); }
private async TT.Task UpdateLoop(IT.TaskScheduler scheduler) { while (!_cts.IsCancellationRequested) { try { var delayMilliseconds = scheduler.IsActive ? 5 : 50; try { await TT.Task.Delay(delayMilliseconds, _cts.Token).ConfigureAwait(false); } catch (TT.TaskCanceledException) { } // ↑Delay なし、専用スレッドで回りっぱなしとかがいいかもしれないし。 scheduler.Update(); } catch (Exception ex) { HasError = true; OnError(ex); } } }
/// <summary> /// コンストラクタ。 /// </summary> /// <param name="scheduler"></param> public TaskRunner(IT.TaskScheduler scheduler) { Scheduler = scheduler; _task = UpdateLoop(scheduler); }
/// <summary> /// 削除。 /// </summary> /// <param name="s"></param> public void Remove(IT.TaskScheduler s) { _schedulers = _schedulers.Remove(s); }
private void OnError(Exception ex, IT.TaskScheduler scheduler) { var d = Error; if (d != null) d(this, new ErrorHandlerAgs(ex, scheduler)); }
/// <summary> /// 追加。 /// </summary> /// <param name="s"></param> public void Add(IT.TaskScheduler s) { _schedulers = _schedulers.Add(s); }
internal ErrorHandlerAgs(Exception error, IT.TaskScheduler scheduler) { Error = error; Scheduler = scheduler; }
public static Task Delay(int milliSecond, IteratorTasks.CancellationToken ct, TaskScheduler scheduler) { var tcs = new TaskCompletionSource<object>(scheduler); Timer timer = null; timer = new Timer(_ => { timer.Dispose(); tcs.SetResult(null); }, null, milliSecond, Timeout.Infinite); ct.Register(() => { timer.Dispose(); tcs.SetCanceled(); }); return tcs.Task; }
public static Task Delay(int milliSecond, IteratorTasks.CancellationToken ct) { return Delay(milliSecond, ct, Task.DefaultScheduler); }
public static IEnumerator Skip(int frames, IteratorTasks.CancellationToken ct) { for (int i = 0; i < frames; i++) { ct.ThrowIfCancellationRequested(); yield return null; } }
public static Task DelayFrame(int frames, IteratorTasks.CancellationToken ct, TaskScheduler scheduler) { return Task.Run(Skip(frames, ct), scheduler); }