我想使用新的跨度来使用SocketAsyncEventArgs将非托管数据直接发送到套接字,但SocketAsyncEventArgs似乎只能接受Memory<byte>,这不能用byte *或IntPtr进行初始化。
那么,有没有办法在SocketAsyncEventArgs中使用span呢
谢谢你的帮助。
发布于 2018-09-19 00:29:13
正如评论中已经提到的,Span在这里是一个错误的工具--你有没有考虑过改用Memory?正如您所说的,SetBuffer method确实接受它作为参数--有什么原因不能使用它吗?
有关堆栈与堆分配如何应用于跨度和内存的详细说明,请参阅this article。它包含了这个使用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
}
}
}发布于 2018-09-17 11:34:22
您应该首先将数据复制到托管内存,使用Marshal或Buffer类。
如果不是,想想当C代码删除返回的指针时,发送数据会发生什么?
发布于 2018-09-21 19:20:53
在SocketAsyncEventArgs (just follow the link)的MSDN页面上有一个完整的示例(以及类的实现)。它显示了类的正确使用,并可能为您提供您正在寻找的指导。
此外,正如Shingo所说,它应该都在托管代码中,而不是在指针中。
https://stackoverflow.com/questions/52210512
复制相似问题