如何使用await / async等待资源

时间:2014-08-24 20:22:18

标签: c# .net asynchronous task-parallel-library async-await

我不完全理解所有.Net异步编程概念(等待,异步,等待,同步上下文等)是如何工作的。

我正在使用套接字,它们需要缓冲区来进行读/写操作,我想要一个BufferAllocator对象来搜索并返回套接字要使用的缓冲区。关键是当没有足够的可用内存(缓冲池为空)时,应用程序应等待缓冲区并在所需的内存量可用时继续。

我该如何实现?

好的,这是我的作业(为了简单起见只是一个演示,这不是我真正的代码):

class Program
{
    private static BufferAllocator _allocator;

    static void Main(string[] args)
    {
        _allocator = new BufferAllocator(100);   // 100 bytes
        Task.Factory.StartNew(async () =>
        {
            await _allocator.GetBufferAsync(40); // 100 - 40 = 60bytes
            await _allocator.GetBufferAsync(40); //  60 - 40 = 20bytes 
            await _allocator.GetBufferAsync(40); //  20 < 40 (wait)
            Console.WriteLine("Worked!");  // <-------+
        }); //                                        |
        Console.ReadKey(); //                         |
        _allocator.ReleaseBuffer(40); // after pessing a key, release 40 bytes
        Console.ReadKey();
    }

}

class BufferAllocator
{
    private int _availableBytes;
    private SemaphoreSlim _signal = new SemaphoreSlim(0, 1);

    public BufferAllocator(int bufferSize)
    {
        _availableBytes = bufferSize;
    }

    public async Task GetBufferAsync(int size)
    {
        while(_availableBytes < size)
            await _signal.WaitAsync();

        _availableBytes -= size;
    }

    public void ReleaseBuffer(int size)
    {
        _availableBytes += size;
        _signal.Release();
    }
}

注意:将有几个插槽并行读写。请给我一个线索。

1 个答案:

答案 0 :(得分:3)

当您实际实现async构造时,您应该使用TaskCompletionSource。将其视为信号对象。它具有Task属性,您可以异步返回到客户端await。并使用TaskCompletionSource方法更新任务的状态(例如SetResult)。这就是一方(生产者)&#34;通知&#34;应该恢复的另一个(该特定任务的消费者)。

当然,您可以使用内置构造(如SemaphoreSlim,基于大小或AsyncAutoResetEvent)。

确保永远不会忘记完成任务(结果,例外或取消)。否则你将面临最令人不快的错误/死锁。