> やりたいことやりたいこと
逐次実行する複数のCoroutineの中で、一連の処理を全部中断したい。
CoroutineRunner.cs
public IEnumerator HogeCoroutine()
{
yield return CoroutineA();
yield return CoroutineB();
yield return CoroutineC();
}
private IEnumerable CoroutineA()
{
...
}
private IEnumerable CoroutineB()
{
...
// ここで一連の処理を全て中断したい
}
private IEnumerable CoroutineC()
{
...
}
> 愚直にやる愚直にやる
キャンセルフラグを持っておいてキャンセルされたら外側のCoroutineでyield breakします。
単純だけどCoroutineが更にネストしたりするとめんどくさい。
CoroutineRunner.cs
private isCancelled = false;
public IEnumerator HogeCoroutine()
{
IEnumerator[] coroutines = new IEnumerator[]
{
CoroutineA(), CoroutineB(), CoroutineC(),
}
foreach(IEnumerator e in coroutines)
{
yield return e;
if(isCancelled) yield break;
}
}
private IEnumerable CoroutineA()
{
...
}
private IEnumerable CoroutineB()
{
...
// ここで一連の処理を全て中断したい
isCancelled = true;
yield break;
}
private IEnumerable CoroutineC()
{
...
}
> Coroutineを分解するCoroutineを分解する
各CoroutineのMoveNextの呼び出しをひとつのループで呼び出す。
ここまでやると後からCoroutineを追加したり、タイムアウトや割り込みを仕込んだりできるので応用が利きます。
CoroutineRunner.cs
public class CoroutineRunner{
private Queue<IEnumerator> queue = new Queue<IEnumerator>();
private bool isRequestedCancel = false;
public Append(params IEnumerator[] coroutines)
{
foreach(var e in coroutines) queue.Enqueue(e);
}
public void Cancel()
{
isRequestedCancel = true;
}
public IEnumerator Coroutine()
{
while (true)
{
if (isRequestedCancel) break;
if (queue.Count == 0) break;
if (peek.MoveNext())
{
yield return peek.Current;
}
else
{
queue.Dequeue();
}
}
}
}
private CoroutineRunner runner = new CoroutineRunner();
public IEnumerator HogeCoroutine()
{
runner.Append(CoroutineA(), CoroutineB(), CoroutineC());
yield return runner.Coroutine();
}
private IEnumerable CoroutineA()
{
...
}
private IEnumerable CoroutineB()
{
...
// ここで一連の処理を全て中断したい
runner.Cancel();
}
private IEnumerable CoroutineC()
{
...
}
ちなみに僕が普段使いしているものはこちらです。
0 件のコメント:
コメントを投稿