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);
}
}