我想使用新的 Span 将非托管数据直接发送到套接字,但似乎 SocketAsyncEventArgs
只能接受无法用 byte *
或 IntPtr
初始化的 Memory<byte>
。
所以,请问有没有办法在 SocketAsyncEventArgs
中使用 Span ?
感谢您的帮助。
正如评论中已经提到的,Span 在这里是错误的工具 - 你是否考虑过使用 Memory?正如你所说,SetBuffer
方法 将其作为参数接受 - 你不能使用它的原因是什么?
另请参阅 this article ,了解关于堆栈分配如何应用于 Span 和 Memory 的良好解释。它包括此示例,使用 readonly Memory<Foo> buffer
:
public struct Enumerable : IEnumerable<Foo>
{
readonly Stream stream;
public Enumerable(Stream stream)
{
this.stream = stream;
}
public IEnumerator<Foo> GetEnumerator() => new Enumerator(this);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public struct Enumerator : IEnumerator<Foo>
{
static readonly int ItemSize = Unsafe.SizeOf<Foo>();
readonly Stream stream;
readonly Memory<Foo> buffer;
bool lastBuffer;
long loadedItems;
int currentItem;
public Enumerator(Enumerable enumerable)
{
stream = enumerable.stream;
buffer = new Foo[100]; // alloc items buffer
lastBuffer = false;
loadedItems = 0;
currentItem = -1;
}
public Foo Current => buffer.Span[currentItem];
object IEnumerator.Current => Current;
public bool MoveNext()
{
if (++currentItem != loadedItems) // increment current position and check if reached end of buffer
return true;
if (lastBuffer) // check if it was the last buffer
return false;
// get next buffer
var rawBuffer = MemoryMarshal.Cast<Foo, byte>(buffer);
var bytesRead = stream.Read(rawBuffer);
lastBuffer = bytesRead < rawBuffer.Length;
currentItem = 0;
loadedItems = bytesRead / ItemSize;
return loadedItems != 0;
}
public void Reset() => throw new NotImplementedException();
public void Dispose()
{
// nothing to do
}
}
}
在 MSDN 页面上有一个完整的示例(以及类的实现)SocketAsyncEventArgs(只需跟随链接)。它展示了该类的正确使用方式,可能会给您所寻找的指导。
此外,正如 Shingo 所说,它应该全部使用托管代码,而不是指针。
你应该先将数据复制到托管内存中,使用Marshal或Buffer类。
如果不这样做,当C代码删除返回的指针时,发送的数据会发生什么?
SocketAsyncEventArgs
。该类的整个目的是作为托管对象池中的一个单元,以减少分配。它试图实现与Span
相同的目标,但以不同的方式(在Span
不存在时)。要将非托管数据直接发送到套接字,您需要使用常规方法的Span
版本(这已经在 此处 上进行了处理),但这不是异步的 - 由于Span
的基于堆栈的特性,它们不能是异步的。 - Jeroen MostertSocketAsyncEventArgs
基础设施,它可以与非托管内存一起使用——你知道的,仅仅是因为我们还没有足够多的与套接字交互的方式。 :-P 然而我不认为它能很好地与当前的SocketAsyncEventArgs
进行互操作。 - Jeroen Mostert