我想使用新的Span使用SocketAsyncEventArgs
直接将非托管数据发送到套接字,但是似乎SocketAsyncEventArgs
仅接受Memory<byte>
,而不能用{{1}进行初始化}或byte *
r。
那么请问有没有一种方法可以对IntPt
使用span?
谢谢您的帮助。
答案 0 :(得分:4)
正如评论中已经提到的,Span是错误的工具-您是否考虑过使用Memory?如您所说,SetBuffer
method确实接受它作为参数-是否有您不能使用它的原因?
另请参阅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
}
}
}
答案 1 :(得分:0)
您应该首先将数据复制到托管内存,使用Marshal或Buffer类。
如果不考虑C代码何时删除返回的指针,发送数据将如何处理?
答案 2 :(得分:0)
在MSDN页面上有SocketAsyncEventArgs (just follow the link)的完整示例(该类的实现)。它显示了该类的正确用法,并可能为您提供所需的指导。
而且,正如Shingo所说,所有内容都应该在托管代码中,而不是指针中。