C#:ManualResetEventでのクラッシュ
-
03-07-2019 - |
質問
msdnのこの記事を使用してコードを記述しました一次ヘルパー
マイコード:
private ManualResetEvent _AllDone = new ManualResetEvent(false);
internal void Initialize(int port,string IP)
{
IPEndPoint _Point = new IPEndPoint(IPAddress.Parse(IP), port);
Socket _Accpt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_Accpt.Bind(_Point);
_Accpt.Listen(2);
while (true)
{
_AllDone.Reset();
_Accpt.BeginAccept(null, 0, new AsyncCallback(Accept), _Accpt);
_AllDone.WaitOne(); <<crash here
}
}
これが起こることで、BeginAcceptにブレークポイントを設定しました(問題があると思っていました)が、通常どおりステップします。しかし、&quot; _AllDone.WaitOne()&quot; -サーバーがクラッシュします。
_allDoneをwin32フォームアプリケーションで使用できない場合-プロジェクトの作成方法
編集
Accept()で_AllDone.Reset()を記述したことを忘れていましたが、そこには行きません。そこにブレークポイントを設定しましたが、行きません。
private void Accept(IAsyncResult async)
{
_AllDone.Set();
Socket _Accpt = (Socket)async.AsyncState;
Socket _Handler = _Accpt.EndAccept(async);
StateObject _State = new StateObject();
_State.workSocket = _Handler;
_Handler.BeginReceive(_State.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), _State);
}
解決
そのため、正しい場合は、ソケット接続が受信されるとすぐに Accept
を再起動し、 Accept
が完了するまで待たずに、同期バージョンの Accept
を使用しない理由。
では、指定されたアドレスとポートにソケットを接続したときにAcceptメソッドを起動しないと言っていますか?それがAcceptが行うことだからです。新しい着信接続を受け入れ、クライアントが接続するまで待機します。そのため、「クラッシュした」と考えているのかもしれません。そして、Acceptメソッドでコードに到達しない理由。
ヒント: Socket.AcceptAsync
編集:着信接続をリッスンする非同期サーバーを設定するには、ManualWaitEventは必要ありません:
internal void Initialize(int port,string IP) {
IPEndPoint _Point = new IPEndPoint(IPAddress.Parse(IP), port);
Socket _Accpt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_Accpt.Bind(_Point);
_Accpt.Listen(2);
_Accpt.BeginAccept(null, 0, new AsyncCallback(Accept), _Accpt);
}
private void Accept(IAsyncResult async) {
Socket _Accpt = (Socket)async.AsyncState;
Socket _Handler;
try {
_Handler = _Accpt.EndAccept(async);
} finally {
_Accpt.BeginAccept(null, 0, new AsyncCallback(Accept), _Accpt);
}
StateObject _State = new StateObject();
_State.workSocket = _Handler;
_Handler.BeginReceive(_State.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), _State);
}
注:終了条件も必要になるため、BeginAcceptが呼び出されません(たとえば、サーバーをシャットダウンする場合)。
他のヒント
Luceroは、アプリケーションが正常に動作することを伝えようとしていると思います。
サーバー側のソケットアプリケーションを使用している場合、基本的には、サーバーにポートに接続し、接続が到着するまで待機するように要求します。接続が到着したら、残りのコードを実行します。
Luceroが言っていたのは、サーバーにメッセージが届かない間、サーバーは設定と待機を続けているため、フリーズしたかのように見えるかもしれません。
コードの場合ですか?