Asynchronous network programming with async/await

后端 未结 2 508
别跟我提以往
别跟我提以往 2021-01-28 08:33

For the past few years, I\'ve developed client/server software using the Asynchronous Programming Model and sockets. This example on MSDN, although overcomplicated with synchron

相关标签:
2条回答
  • 2021-01-28 08:43

    Actually, the old APM supported by the Socket class used a special thread pool, the IOCP ("I/O Completion Port") thread pool, and rather than assigning threads "when data is received", actually assigned threads as I/O operations are initiated, but in a way that allows a single thread (or small number of threads…e.g. as many as there are cores on the system) to handle a large number of socket objects and operations.

    As far as how to use the new async/await style API, unfortunately the Socket class didn't get any direct async love. However, all of the wrappers did. The most straight-forward replacement is to use the NetworkStream class, and use ReadAsync() and WriteAsync(), which are awaitable methods.

    If you want to still use the Socket API (essentially) directly, you'll have to wrap it yourself with an awaitable implementation. IMHO, a very good resource explaining one possible approach for doing this is here: Awaiting Socket Operations

    0 讨论(0)
  • 2021-01-28 08:54

    The Task Asynchronous Pattern and its used keywords async-await lets you take use of async I/O (as you said) but in a "cleaner" fashion.

    Instead of using BeginXXX and EndXXX methods and passing callbacks between each other, you can simply await on an async method which returns an awaitable (A Task is an example of one).

    For example, lets make an example using HttpClient:

    public async Task DoGetWebRequestAsync()
    {
        var httpClient = new HttpClient();
        await httpClient.GetAsync(url);
    }
    

    What this will do is once the method hits the await keyword, it will yield control back to the calling method, creating a state-machine behind the scenes (which will be in charge of executing the continuation, propagating exceptions, etc..) and resume via an IOCP (IO Completion port, allocated by the ThreadPool) once the IO work is complete.

    The TAP also offers a way to turn the old APM pattern into the TAP using TaskFactory.FromAsync:

    FileInfo fi = new FileInfo(path);
    byte[] data = null;
    data = new byte[fi.Length];
    
    FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read,
                                   FileShare.Read, data.Length, true);
    
    //Task<int> returns the number of bytes read
    Task<int> task = Task<int>.Factory.FromAsync(
            fs.BeginRead, fs.EndRead, data, 0, data.Length, null);
    

    Edit:

    How to use async is simple. For example, with FileStream:

    public async Task<byte[]> ReadBufferAsync(string path)
    {
        FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read,
                                    FileShare.Read, data.Length, true);
    
        // Read some bytes, not all, just for the example.
        byte[] buffer = new byte[2048];
        await fs.ReadAsync(buffer, 0, buffer.Length);
    
        return buffer;
    }
    

    You mark you method async so you can use the await keyword inside it, and then simply await on the method which reads.

    0 讨论(0)
提交回复
热议问题