简体   繁体   English

C#使用span与SocketAsyncEventArgs

[英]C# Using span with SocketAsyncEventArgs

I would like to use new Span to send unmanaged data straight to the socket using SocketAsyncEventArgs but it seems that SocketAsyncEventArgs can only accept Memory<byte> which cannot be initialized with byte * or IntPt r. 我想使用新的Span使用SocketAsyncEventArgs将非托管数据直接发送到套接字,但似乎SocketAsyncEventArgs只能接受无法用byte *IntPt r初始化的Memory<byte>

So please is there a way to do use span with SocketAsyncEventArgs ? 那么有没有办法使用SocketAsyncEventArgs span?

Thank you for your help. 谢谢您的帮助。

As already mentioned in the comments, Span is the wrong tool here - have you looked at using Memory instead? 正如评论中已经提到的,Span在这里是错误的工具 - 你看过使用内存吗? As you stated, the SetBuffer method does accept that as a parameter - is there a reason you can't use it? 正如您所说, SetBuffer方法确实接受它作为参数 - 是否有理由不能使用它?

See also this article for a good explanation on how stack vs heap allocation applies to Span and Memory. 有关堆栈与堆分配如何应用于Span和Memory的详细说明,请参阅本文 It includes this example, using a readonly Memory<Foo> buffer : 它包括这个例子,使用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
        }
    }
}

You should copy the data to managed memory first, use Marshal or Buffer class. 您应该首先将数据复制到托管内存,使用Marshal或Buffer类。

If not think about when the C code delete the returned pointer what will happen to the send data? 如果不考虑C代码何时删除返回的指针,发送数据会发生什么?

There's a complete example (and implementation of the class) on the MSDN page for the SocketAsyncEventArgs (just follow the link) . SocketAsyncEventArgs的MSDN页面上有一个完整的示例(以及该类的实现) (只需按照链接) It shows the proper use of the class and may give you the guidence you're looking for. 它显示了课程的正确使用,并可能为您提供您正在寻找的指导。

Also, as Shingo said, it should all be in managed code, not in pointers. 另外,正如Shingo所说,它应该都是托管代码,而不是指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM