7

我有一个连接类,它有几个异步方法,如 SendText、SendImage 等。

连接类有一个 Disconnect 方法,当它被调用时,我必须小心不要在所有异步方法完成执行之前开始更改类的内部状态。

我相信实现这一点的一个好方法是简单地保持正在执行的操作总数,然后当我想断开连接时,我可以简单地设置 Disconnecting = true 然后等待计数达到 0

我正在考虑类似的事情

class ReferenceCounter
{
    void Increment();

    void Decrement();

    async Task WaitForCounterToReachZero();
}

然后当异步操作开始时我可以做

refCounter.Increment();

当它结束时

refCounter.Decrement();

在 Disconnect 方法中

disconnecting = true;
taskCancellationSource.Cancel();
await refCounter.WaitForCounterToReachZero();
Cleanup();

有没有像这样的内置 .NET 类?

或者对我来说更重要的是,有没有更好的方法来做到这一点?

如果它是同步代码,它会很简单

lock (thisLock)
{
    while (counter > 0)
        Monitor.Wait(thisLock);
}

我刚刚发现内置的 CountdownEvent 类做同样的事情,但它没有异步等待方法,也没有任何事件,所以我不得不阻止。

4

1 回答 1

6

好吧,假设您将其设为 0后永远不会再增加,您可以执行以下操作:

public class Latch
{
    private int count = 0;
    private readonly TaskCompletionSource<object> tcs =
        new TaskCompletionSource<object>();

    public void Increment()
    {
        Interlocked.Increment(ref count);
    }

    public void Decrement()
    {
        if (Interlocked.Decrement(ref count) == 0)
        {
            tcs.TrySetValue(null);
        }
    }

    public Task Task { get { return tcs.Task; } }
}

然后你可以等待someLatch.Task。或者,您可以使闩锁本身可等待:

public TaskAwaiter GetAwaiter()
{
    return tcs.Task.GetAwaiter();
}

您可能应该考虑如何防止“下降到 0 后计数上升”方面 - 想想您希望它做什么。(在上面的代码中,一旦设置了 TCS 的值,进一步的等待将立即完成。)

于 2013-01-14T06:46:30.233 回答