可以等待的异步计数器 [英] An asynchronous counter which can be awaited on

查看:98
本文介绍了可以等待的异步计数器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个连接类,它具有几个异步方法,例如SendText,SendImage等.

I have a connection class which has several async methods such as SendText, SendImage etc.

连接类具有Disconnect方法,在调用它时,我必须注意不要在所有异步方法完成执行之前开始更改类的内部状态.

The connection class has a Disconnect method, and when it is called I have to be careful not to start changing the inner state of the class before all async methods have completed execution.

我相信实现此目的的一种好方法是简单地保持运行中正在运行的操作总数,然后当我想断开连接时,我可以简单地将Disconnecting = true设置为零,然后等待计数达到0

I believe a good way to achieve this is to simply keep a running total of the number of operations in execution, and then when I want to Disconnect I can simply set Disconnecting = true and then wait for the count to reach 0

我正在考虑与此类似的东西

I'm thinking of something along the lines of this

class ReferenceCounter
{
    void Increment();

    void Decrement();

    async Task WaitForCounterToReachZero();
}

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

Then when an async operation starts I could do

refCounter.Increment();

结束时间

refCounter.Decrement();

并在Disconnect方法内

and inside the Disconnect method

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

是否有任何内置的.NET类?

Are there any built in .NET classes like this?

或更重要的是,有没有更好的方法?

Or more importantly for me, is there a better way of doing this?

如果它是同步代码,它将像

If it was synchronous code it would be as simple as

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

我刚刚发现内置CountdownEvent类,它具有相同的功能,但是它没有异步的Wait方法,也没有任何事件,所以我必须阻止.

I just found the built in CountdownEvent class which does the same thing, but it has no async Wait method nor does it have any events, so I'd have to block.

推荐答案

好吧,假设您永远不会在 设为0后再次递增,则可以执行以下操作:

Well, assuming you'll never increment again after you make it 0, you could do something like this:

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.另外,您可以使闩锁本身可以等待:

Then you can await someLatch.Task. Alternatively, you could make the latch itself awaitable:

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

您可能应该考虑如何防止计数下降到0后计数增加"方面-考虑您要执行的操作. (在上面的代码中,一旦设置了TCS的值,将立即完成进一步的等待.)

You should probably consider how you want to guard against the "count rises after getting down to 0" aspect thuogh - think about what you'd want it to do. (In the code above, once the TCS's value has been set, further awaits will complete immediately.)

这篇关于可以等待的异步计数器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆