Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何为异步等待调用创建包装器?_C#_Asynchronous_Async Await - Fatal编程技术网

C# 如何为异步等待调用创建包装器?

C# 如何为异步等待调用创建包装器?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,据我所知,没有内置(或框架扩展)支持ConnectAsync/acceptsync/sendaync/ReceiveAsync等。。如何编写异步等待机制支持的自己的包装器。例如,我的当前代码处理内联和回调上的ReceiveAsync(在SocketAsyncEventArgs中指定): 诀窍是用来处理这种情况 我在博客上写了这件事。有关详细信息,请参阅。您还可以编写一个定制的watiable,在这种情况下我更喜欢它。这是微软的Stephen Toub的一项技术。您可以在这里阅读更多有关此技术的

据我所知,没有内置(或框架扩展)支持
ConnectAsync
/
acceptsync
/
sendaync
/
ReceiveAsync
等。。如何编写异步等待机制支持的自己的包装器。例如,我的当前代码处理内联和回调上的
ReceiveAsyn
c(在
SocketAsyncEventArgs
中指定):

诀窍是用来处理这种情况


我在博客上写了这件事。有关详细信息,请参阅。

您还可以编写一个定制的watiable,在这种情况下我更喜欢它。这是微软的Stephen Toub的一项技术。您可以在这里阅读更多有关此技术的信息。

这是一个值得期待的习俗:

public sealed class SocketAwaitable : INotifyCompletion
{
    private readonly static Action SENTINEL = () => { };
    internal bool m_wasCompleted;
    internal Action m_continuation;
    internal SocketAsyncEventArgs m_eventArgs;
    public SocketAwaitable(SocketAsyncEventArgs eventArgs)
    {
        if (eventArgs == null) throw new ArgumentNullException("eventArgs");
        m_eventArgs = eventArgs;
        eventArgs.Completed += delegate
        {
            var prev = m_continuation ?? Interlocked.CompareExchange(
                ref m_continuation, SENTINEL, null);
            if (prev != null) prev();
        };
    }
    internal void Reset()
    {
        m_wasCompleted = false;
        m_continuation = null;
    }
    public SocketAwaitable GetAwaiter() { return this; }
    public bool IsCompleted { get { return m_wasCompleted; } }
    public void OnCompleted(Action continuation)
    {
        if (m_continuation == SENTINEL ||
            Interlocked.CompareExchange(
                ref m_continuation, continuation, null) == SENTINEL)
        {
            Task.Run(continuation);
        }
    }
    public void GetResult()
    {
        if (m_eventArgs.SocketError != SocketError.Success)
            throw new SocketException((int)m_eventArgs.SocketError);
    }
}
要添加到socket类并使其方便的一些扩展方法:

public static class SocketExtensions
{
    public static SocketAwaitable ReceiveAsync(this Socket socket,
        SocketAwaitable awaitable)
    {
        awaitable.Reset();
        if (!socket.ReceiveAsync(awaitable.m_eventArgs))
            awaitable.m_wasCompleted = true;
        return awaitable;
    }
    public static SocketAwaitable SendAsync(this Socket socket,
        SocketAwaitable awaitable)
    {
        awaitable.Reset();
        if (!socket.SendAsync(awaitable.m_eventArgs))
            awaitable.m_wasCompleted = true;
        return awaitable;
    }
    // ... 
}
使用中:

    static async Task ReadAsync(Socket s)
    {
        // Reusable SocketAsyncEventArgs and awaitable wrapper 
        var args = new SocketAsyncEventArgs();
        args.SetBuffer(new byte[0x1000], 0, 0x1000);
        var awaitable = new SocketAwaitable(args);

        // Do processing, continually receiving from the socket 
        while (true)
        {
            await s.ReceiveAsync(awaitable);
            int bytesRead = args.BytesTransferred;
            if (bytesRead <= 0) break;

            Console.WriteLine(bytesRead);
        }
    }
静态异步任务ReadAsync(套接字)
{
//可重用的SocketAsyncEventArgs和可等待包装器
var args=new SocketAsyncEventArgs();
参数SetBuffer(新字节[0x1000],0,0x1000);
var awaitable=新的SocketAwaitable(args);
//进行处理,不断地从插座接收数据
while(true)
{
等待s.ReceiveAsync(可等待);
int bytesRead=args.bytesttransfered;
如果(bytesRead对于套接字内容,.NET4.5中有一个包装器。如果您使用的是.NET4,我建议您使用APM,而不是基于事件的异步模式。它更容易转换为
任务

public static class SocketExtensions
{
    public static SocketAwaitable ReceiveAsync(this Socket socket,
        SocketAwaitable awaitable)
    {
        awaitable.Reset();
        if (!socket.ReceiveAsync(awaitable.m_eventArgs))
            awaitable.m_wasCompleted = true;
        return awaitable;
    }
    public static SocketAwaitable SendAsync(this Socket socket,
        SocketAwaitable awaitable)
    {
        awaitable.Reset();
        if (!socket.SendAsync(awaitable.m_eventArgs))
            awaitable.m_wasCompleted = true;
        return awaitable;
    }
    // ... 
}
    static async Task ReadAsync(Socket s)
    {
        // Reusable SocketAsyncEventArgs and awaitable wrapper 
        var args = new SocketAsyncEventArgs();
        args.SetBuffer(new byte[0x1000], 0, 0x1000);
        var awaitable = new SocketAwaitable(args);

        // Do processing, continually receiving from the socket 
        while (true)
        {
            await s.ReceiveAsync(awaitable);
            int bytesRead = args.BytesTransferred;
            if (bytesRead <= 0) break;

            Console.WriteLine(bytesRead);
        }
    }