Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

It's neat that with UniTaskCompletionSource we are able to wait on the Task multiple times, and I'm kind of using it as an event/notification system. The problem is, I can't figure out how to cancel or "unsubscribe" from such a source. It looks like the standard C# way is to just cancel the TaskCompletionSource instead, but that would mean sending a canceled message to all the other waiters.

Is there a way to cancel this or am I just using it wrong?

You must be logged in to vote

Replies: 1 comment

Comment options

You don’t “unsubscribe” by cancelling the source. You cancel your own await.

Use a CancellationToken on the awaiting side and attach it to the task. That cancels only your waiter and leaves the source + other waiters untouched:

using Cysharp.Threading.Tasks;
using System.Threading;

async UniTask ListenAsync(UniTaskCompletionSource source, CancellationToken ct)
{
    // This await will be cancelled if ct is cancelled, but the source stays alive.
    await source.Task.AttachExternalCancellation(ct);

    // if we got here, the source completed and you can handle the signal
}

Unsubscribing becomes just cts.Cancel():

var cts = new CancellationTokenSource();
var listen = ListenAsync(mySource, cts.Token);

// later, if this listener should stop waiting:
cts.Cancel(); // only this waiter is cancelled; others keep waiting

If you’re using UniTaskCompletionSource as an event/notification, make it single-shot and replace it after firing:

class Signal
{
    UniTaskCompletionSource tcs = new UniTaskCompletionSource();

    public UniTask NextAsync(CancellationToken ct)
        => tcs.Task.AttachExternalCancellation(ct);

    public void Fire()
    {
        tcs.TrySetResult();               // complete current waiters
        tcs = new UniTaskCompletionSource(); // new round for the next event
    }
}

(Alternative for stream-style events: use AsyncReactiveProperty/IUniTaskAsyncEnumerable/Channel, but for simple “next signal” the pattern above is enough.)

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
🙏
Q&A
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.