0

私は.NetのSocket.BeginReceiveメソッドを使用しましたが、EndReceiveメソッドからデータを取得している間、AutoResetEvent.waitoneブロックを使用してEndReceiveコードスレッドを無限に使用しましたBeginReceiveが機能しないことがわかりました。すべてのスレッドがブロックされました。タイマーが終了し、データを再び取得できるイベントを通知するまで、何も取得しません。BeginReceive は非同期メソッドではありませんか?

var sock= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

sock.BeginReceive(buffer, 0, 1024, SocketFlags.None, i => {
    var sock= (Socket)i.AsyncState;
    int readNum=sock.EndReceive(i);
    var reset= new AutoResetEvent(false);
    Timer timer = new Timer({ Thread.Sleep(1000000000); reset.set() });

    reset.WaitOne(Timeout.Infinite);
    time.Dispose();
} ,sock);

タイマーを破棄するだけで、待機する新しいスレッドを作成する必要があります!!

4

1 に答える 1

0

,は一時的なクロージャーAutoResetEvente囲まれているため、EndReceiveコードを処理するために作成されたスレッドは無期限に待機します。

コードを次のようにリファクタリングしたほうがよいでしょう。

bool stopped = false;
var timer = null;

void MainFunction()
{
    var buffer = new byte[1024];
    var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    sock.BeginReceive(buffer, 0, 1024, SocketFlags.None, new AsyncCallback(ReadCallback), sock);
}

void ReadCallback(IAsyncResult ar)
{
    var sock = (Socket)ar.AsyncState;

    int readNum = sock.EndReceive(ar);

    // begin receiving again as long as we shouldn't be stopped
    if (stopped == false)
    {
        sock.BeginReceive(buffer, 0, 1024, SocketFlags.None, new AsyncCallback(ReadCallback), sock);
    }

    if (timer == null)
    {
        Timer timer = new Timer({ Thread.Sleep(1000000000); stopped = true; });
    }
}

リソースが空いていることを通知する必要がありSetます。AutoResetEventあなたが提供したものには、そのためのコードはありません。

http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspxでいくつかの例とドキュメントを参照してください。

于 2013-08-02T11:12:41.137 に答える