UniRx의 From Coroutine에서 약간 빠져들면.

9559 단어 UniRxUnity
UniRx의 From Coroutine에 빠져서 호출된 처리 방법을 봤습니다.
도면을 만들고 싶어서 From Coroutine 주위의 구조를 고려했다.
예를 들어, 다음 코드가 있다고 가정합니다.

    class Hoge
    {
        public bool flag = true;
    }
    private Hoge hoge = new Hoge();
    System.IDisposable disposable = null;

    public void ExecMyCoroutine()
    {
        disposable = Observable.FromCoroutine(() => Coroutine()).Subscribe();
    }

    public void StopMyCoroutine()
    {
        disposable.Dispose();
        hoge = null;
    }

    public IEnumerator Coroutine()
    {
        Debug.Log("Coroutine START!!");
        yield return new WaitUntil(() => !hoge.flag);
        Debug.Log("Coroutine END!!");
    }
Exec My Coroutine라고 하면 코르크가 뛰고, Stop My Coroutine를 치면 코르크가 멈춘다.
"멈출 때 바로 끝날 것 같아서 hoge도 비울 수 있어요."
이런 상황에서 이렇게 하면 실수를 할 수 있다.
또한 다음의 Custom Yield Instruction을 정의하여 From Coroutine에서 주행하는 코르크에서 Yield에서 기다려도 멈추지 않습니다.

    class Hoge : CustomYieldInstruction
    {
        int count = 0;
        public override bool keepWaiting
        {
            get
            {
                Debug.Log("count:" + count);
                if (count++ >= 3000)
                {
                    return false;
                }
                return true;
            }
        }
        public bool flag = true;
    }

    public void ExecMyCoroutine()
    {
        disposable = Observable.FromCoroutine(() => Coroutine()).Subscribe();
    }

    public void StopMyCoroutine()
    {
        disposable.Dispose();
    }

    public IEnumerator Coroutine()
    {
        Hoge hoge = new Hoge();
        Debug.Log("Coroutine START!!");
        yield return hoge;
        Debug.Log("Coroutine END!!");
    }
그나저나 이렇게 하면 멈춘다.
    public IEnumerator Coroutine()
    {
        Debug.Log("Coroutine START!!");
        Hoge hoge = new Hoge();
        while (hoge.keepWaiting)
        {
            yield return null;
        }
        Debug.Log("Coroutine END!!");
    }
이거, 내가 많이 쫓아봤는데 프롬코루틴의 처리는 다음과 같다.

내부적으로 Wrap Enumerator는 실제로 작동하는 코르크입니다.
실제로 우리가 전달하는 코르크 단백질은 항상 Wrap Enumerator 내부에서 MoveNext를 계속 호출하여 순환의 마지막에
순환이 종료되었는지 또는 취소되었는지 확인하고 문제가 없으면 다음 순환입니다.
순환의 마지막에 Current에 대한 yield return이 있었던 것 같아요.
Custom Yield Instruction의 경우keep Waiting이 false가 되기 전까지 그곳에서 기다렸기 때문에 거기서부터 UniRx도 통제할 수 없는 구역인 것 같습니다.
이 순환이 끝날 때.
cancellationToken.IsCancellationRequested가 사실인지 확인 중이기 때문에 여기에 도착하지 않으면 Dispose를 호출해도 멈추지 않습니다.
이미 알고 있는 문제일지 모르지만 우선 프롬코루틴은 이런 중독점이 있기 때문에 비망록만 남긴다.

뱀발


그나저나 이 Custom Yield Instruction이 Custom Yield Instruction인지 확인해 보세요. Custom Yield Instruction이라면 감시도 잘 해주실 거죠?
그래서 나는 Wrap Enumerator를 고쳐 썼다.
결국 기대한 대로 움직였죠. 물론 지적 호기심이었기 때문에 실제 업무에서는 그럴 수 없었죠.
var customYieldInstruction = enumerator.Current as CustomYieldInstruction;
if (customYieldInstruction != null)
{
    while (customYieldInstruction.keepWaiting && !cancellationToken.IsCancellationRequested)
    {
        yield return null;
    }
}
else
{
    yield return enumerator.Current; // yield inner YieldInstruction
}

좋은 웹페이지 즐겨찾기