Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Several questions about canceling subscriptions and re -subscribing #299

Open
lsenala opened this issue Feb 2, 2025 · 2 comments
Open

Comments

@lsenala
Copy link

lsenala commented Feb 2, 2025

public class PlayerUnit : Unit {
    public ATBB aTBB;
    CancellationTokenSource cts;
    Vector3 targetPos;
    IAbility ability; 
    bool isDisposed=false;
    protected override void Awake()
    {
        base.Awake();
        aTBB.ui.ability.Subscribe(s=>SelectAbility(s));
    }
    private void SelectAbility((string, string) s){
        cts=new();
        if(!abilites.ContainsKey(s.Item1)||abilites[s.Item1].FirstOrDefault(Ability=>Ability.AbilityName==s.Item2)==null){
            cts.Cancel();
            cts.Dispose();
            ability.CancelAbility(this);
            isDisposed=true;
            Debug.Log("Cancel");
            return;// 
        }
        Observable.EveryUpdate(cts.Token)
        .TakeWhile(_=>abilites.ContainsKey(s.Item1)&&!cts.IsCancellationRequested)
        .Subscribe(_=>{
            Debug.Log("Update"); 
            ability=abilites[s.Item1].FirstOrDefault(Ability=>Ability.AbilityName==s.Item2);
            targetPos=aTBB.cam.hitPoint.transform.position;
            ability.UseAbility(this,targetPos);
        });
    }
}
@lsenala
Copy link
Author

lsenala commented Feb 2, 2025

1.SelectAbility() will be called multiple times. I may need to create a cts each time I call this method. The problem is that the Cancel branch here does not really cancel the Update below. I guess the reason is that Cancel only cancels the new cts, and the old cts, which is the cts from the last call to this method, is not dispose().
2.I don't quite understand the mechanism of CancellationTokenSource. It seems that it is not null after dispose(), so I probably can't use null check to check whether a new cts is needed.
3.Is there any difference between filling cts.Token in the parameters of EveryUpdate() and AddTo(cts.Token) at the end?
4.In the code, if I don't fill in &&!cts.IsCancellationRequested in TakeWhile(), I can't cancel the subscription. Whether it is AddTo() or filling in cts.Token in EveryUpdate(), I can't cancel the subscription. Remember that SelectAbility() is a method that is called multiple times. For example, it is called once when a button is pressed.
5.That's all for now. I still don't quite understand how to unsubscribe and resubscribe, because each time I subscribe and unsubscribe, my ability.UseAbility(this, targetPos); and ability.CancelAbility(this); are executed differently, so I guess I need to unsubscribe and resubscribe frequently, and targetPos needs to be updated, so using events is not appropriate.I probably need to create a new cts in this method.

@neuecc
Copy link
Member

neuecc commented Feb 3, 2025

Regarding point 3:
When you pass a CancellationToken to EveryUpdate, it will emit OnCompleted and stop the event stream when cancelled.
Writing AddTo(cts.Token) will end the event stream subscription (it Dispose the subscription linked to the cancellation).
I cannot answer about other details of your application code.
However, frequent unsubscribing and resubscribing should be avoided as it increases code complexity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants