Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#,异步任务和NetworkStream.beginhead,如何保证缓冲区赢得';不会被覆盖吗?_C#_Asynchronous - Fatal编程技术网

C#,异步任务和NetworkStream.beginhead,如何保证缓冲区赢得';不会被覆盖吗?

C#,异步任务和NetworkStream.beginhead,如何保证缓冲区赢得';不会被覆盖吗?,c#,asynchronous,C#,Asynchronous,我试图用C语言编写一段代码,以异步读取TcpClient。这是我的密码: using System; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; class Connection { private TcpClient socket; private NetworkStream socketStream; private byte[] buffer; priv

我试图用C语言编写一段代码,以异步读取TcpClient。这是我的密码:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

class Connection
{
    private TcpClient socket;
    private NetworkStream socketStream;
    private byte[] buffer;
    private int bytesRead;
    private Task<int> readTask;

    public Connection(TcpClient socket)
    {
        this.socket = socket;
        socketStream = socket.GetStream();
        buffer = new byte[4096];

        readTask = Task.Factory.FromAsync<byte[], int, int, int>(
            this.socketStream.BeginRead
            , this.socketStream.EndRead
            , this.buffer
            , 0
            , this.buffer.Length
            , null
        );
        readTask.ContinueWith(
            (task) => {
                this.bytesRead = (int)task.Result;
                //Do something with buffer.
            }
            , TaskContinuationOptions.OnlyOnRanToCompletion
        );
    }
}
使用系统;
Net系统;
使用System.Net.Sockets;
使用System.Threading.Tasks;
类连接
{
专用TcpClient套接字;
专用网络流socketStream;
专用字节[]缓冲区;
私有int字节读;
私有任务读取任务;
公共连接(TCP客户端套接字)
{
this.socket=socket;
socketStream=socket.GetStream();
缓冲区=新字节[4096];
readTask=Task.Factory.FromAsync(
this.socketStream.BeginRead
,this.socketStream.EndRead
,这是缓冲区
, 0
,this.buffer.Length
无效的
);
readTask.ContinueWith(
(任务)=>{
this.bytesRead=(int)task.Result;
//对缓冲区做些什么。
}
,TaskContinuationOptions.OnlyOnRanToCompletion
);
}
}

问题是异步起始将尝试写入连接对象的缓冲区,一旦新数据到达,旧数据将被覆盖,不管它是否被使用。我应该如何解决这个问题?好吧,这应该和闭包有关,但我不知道怎么做

您必须有一组需要处理的缓冲区。您只需分配一个本地缓冲区(
var buffer=new byte[4096];
),然后将该缓冲区添加到continuation中的集合(可能是
Stack
)。您可能还需要通知另一个线程来处理队列中的新数据

例如:

class Connection
{
    private TcpClient socket;
    private NetworkStream socketStream;
    private int bytesRead;
    private Task<int> readTask;
    private Stack<byte[]> buffersToProcess;
    private readonly object lockObject = new object();

    public Connection(TcpClient socket)
    {
        this.socket = socket;
        socketStream = socket.GetStream();
        var buffer = new byte[4096];

        readTask = Task.Factory.FromAsync<byte[], int, int, int>(
            this.socketStream.BeginRead
            , this.socketStream.EndRead
            , buffer
            , 0
            , buffer.Length
            , null
            );
        readTask.ContinueWith(
            (task) =>
                {
                    this.bytesRead = (int) task.Result;
                    var actualBytes = new byte[bytesRead];
                    Array.Copy(buffer, 0, actualBytes, 0, bytesRead);
                    lock (lockObject)
                    {
                        buffersToProcess.Push(actualBytes);
                    }
                    // TODO: do something with buffersToProcess
                }
            , TaskContinuationOptions.OnlyOnRanToCompletion
            );
    }
}
类连接
{
专用TcpClient套接字;
专用网络流socketStream;
私有int字节读;
私有任务读取任务;
私有堆栈缓冲进程;
私有只读对象lockObject=新对象();
公共连接(TCP客户端套接字)
{
this.socket=socket;
socketStream=socket.GetStream();
var buffer=新字节[4096];
readTask=Task.Factory.FromAsync(
this.socketStream.BeginRead
,this.socketStream.EndRead
缓冲器
, 0
,缓冲区。长度
无效的
);
readTask.ContinueWith(
(任务)=>
{
this.bytesRead=(int)task.Result;
var actualBytes=新字节[bytesRead];
复制(缓冲区,0,实际字节,0,字节读取);
锁定(锁定对象)
{
buffersToProcess.Push(实际字节);
}
//TODO:使用buffersToProcess执行某些操作
}
,TaskContinuationOptions.OnlyOnRanToCompletion
);
}
}

但是,您确实没有提供足够的信息来真正说明您在这种情况下真正需要什么。e、 g.为什么之前的缓冲区还没有被处理?

您必须有一个需要处理的缓冲区集合。您只需分配一个本地缓冲区(
var buffer=new byte[4096];
),然后将该缓冲区添加到continuation中的集合(可能是
Stack
)。您可能还需要通知另一个线程来处理队列中的新数据。但是,您确实没有提供足够的信息来真正说明您在这种情况下真正需要什么。e、 g.为什么之前的缓冲区还没有被处理?我已经有了另一个版本的代码,可以正常使用
线程
。但在这里,我试图重写代码以使用
任务
异步
委托。顺便说一句,为了让您的解决方案发挥作用,我需要能够在第一个
任务中将缓冲区复制到
堆栈中。我的意思是,不能保证在第二个
任务开始之前,不会执行第一个任务的另一个实例。事实上,现在我想起来了,让这段代码始终工作的唯一方法是第一个任务返回一个新创建的缓冲区,以便第二个任务可以使用它。但是我不知道怎么做!如果是本地分配的缓冲区,每个任务都有自己的缓冲区。那么我必须问一下,当在第一个任务中分配本地分配的缓冲区时,您将如何在第二个任务中访问它?我的意思是,这肯定会解决我的问题。编译器将捕获外部变量并将其生存期延长到延续中,并使其“事后”可访问。我非常感谢您的努力,但如何保证第一个任务在第二个任务复制缓冲区之前不会覆盖缓冲区?“第二个任务”,你的意思是说与
相连的
ContinueWith
在第一个任务完成时被调用,它不做任何其他事情,就我所知,第一个任务异步完成后会调用
ContinueWith
,这意味着在执行
ContinueWith
之前,第一个任务总是有机会覆盖缓冲区。我错了吗?第一个任务完成了,它没有做任何其他事情。延续可能与调用
fromsync
的原始线程异步,但它与该任务不异步,因为该任务已完成。在继续中,如果尚未读取所有数据,则可以开始另一次读取(从而引入两个异步操作,可能会争夺同一内存);但这是一项新任务。首先感谢你的耐心。其次,这是我在脑海中想到的场景:考虑两个片段从客户端发送到服务器。它们到达服务器的距离如此之近(及时),以至于第二个任务无法找到复制缓冲区的机会。那不可能吗?我