0

TcpClient から非同期的に読み取るコードを C# で記述しようとしています。これが私のコードです:

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
        );
    }
}

問題は、非同期の BeginRead が Connection オブジェクトのバッファを上書きしようとし、新しいデータが到着すると、それが消費されたかどうかに関係なく、古いデータが上書きされることです。この問題にどのように取り組むべきですか?私の知る限り、クロージャーと関係があるはずですが、その方法がわかりません!

4

1 に答える 1

2

処理する必要があるバッファのコレクションが必要です。単純にローカル バッファ ( ) を割り当ててから、そのバッファを継続var buffer = new byte[4096];のコレクション (おそらく ) に追加することができます。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
            );
    }
}

しかし、この状況に本当に必要なものを本当に伝えるのに十分な情報を提示していません。たとえば、前のバッファがまだ処理されていないのはなぜですか?

于 2013-02-15T17:49:35.333 に答える