2011-07-19 36 views
5

TcpClient.BeginConnect/TcpClient.EndConnectコンボでサーバーに接続しようとしています。しかし、いくつかのことは、必要なときには機能しません。ソケットが閉じているときにTcpClient.EndConnectがNullReferenceExceptionをスローする

次のようなシナリオがある:TcpClient.BeginConnect

  • サーバへ

    • コール(テスト目的のために)意図的にオフラインになっている - 従ってない接続が行われないことができます。
    • Iは
    • TcpClient接続コールバックメソッドが所定IAsyncResult
    • NullReferenceExceptionEndConnectで発生するとTcpClient.EndConnect方法にIAsyncResult
    • コール(を与える起こる(client.Close()closes the socket which in turn stops the async operationプロセスで呼び出される)アプリケーションを閉じます?
    • 最後のフォーム(ウィンドウ)が閉じられたので、アプリは終了する必要がありますが、少なくとも、BeginConnectの操作が完了するまで(これは、コールバックが既に呼び出されているので、奇妙です)。ここでは何が起こる

    exception

    NullReferenceExceptionがキャッチされていることです。上の写真からわかるように、clientでもarnullです。問題は、MSDN documentation for the EndConnectにこの例外がスローされた場合は言及していないことです。

    基本的に、私は何が起こっているのか分かりません。問題は、(接続操作がまだタイムアウトを待っているかのように)アプリケーションが終了するのを待たなければならないことです。 サーバがオンラインになっている場合、サーバは正しく接続され、接続が切断されます。

    この文脈でNullReferenceException何を意味するのでしょうか?どのように接続を確立することができない場合に閉じるアプリケーションをブロックする操作BeginConnectを回避するには?


    その他の注意事項(コメントで要求):ここで

    は、クライアントを作成するためのコードである(クライアントがメンバ変数である。また、

    public void Connect() 
    { 
        try 
        { 
         lock (connectionAccess) 
         { 
          if (State.IsConnectable()) 
          { 
           // Create a client 
           client = new TcpClient(); 
           client.LingerState = new LingerOption(false, 0); 
           client.NoDelay = true; 
    
           State = CommunicationState.Connecting; 
    
           client.BeginConnect(address, port, onTcpClientConnectionEstablished, null); 
          } 
          else 
          { 
           // Ignore connecting request if a connection is in a state that is not connectable 
          } 
         } 
        } 
        catch 
        { 
         Close(true); 
        } 
    } 
    

    Closeメソッド:

    public void Close(bool causedByError) 
    { 
        lock (connectionAccess) 
        { 
         // Close the stream 
         if (clientStream != null) 
          clientStream.Close(); 
    
         // Close the gateway 
         if (client != null) 
          client.Close(); 
    
         // Empty the mailboxes 
         incomingMailbox.Clear(); 
         outgoingMailbox.Clear(); 
    
         State = causedByError ? CommunicationState.CommunicationError : CommunicationState.Disconnected; 
        } 
    } 
    
  • +0

    InnerExceptionは、何がNULLであったかについての詳細情報を提供しますか? – Tremmors

    +0

    @Tremmors Nope。 InnerExceptionはnullです。 StackTraceのヘルプもありません(onTcpClientConnectionEstablished> EndConnect)。 : –

    +0

    はい、明らかにフレームワークのバグです.TcpClientがEndConnect()が呼び出される前に閉じられている場合は、ObjectDisposedExceptionをスローするはずですが、NullReferenceExceptionを最初の1,2回取得したように見えて、ObjectDisposedExceptionをスローします。私はあなたが単にObjectDisposedException(つまり、 "接続のタイムアウト/失敗/あなたがClose()"と呼んだその他の理由)と同じように扱うことをお勧めします。しかし、リソースが漏れているかどうかはわかりませんここではEndConnect()が完了していないので、おそらくGCが処理できないものはありません:) – Tom

    答えて

    0

    私も同様のエラーが発生し、このコードを使用してしまいました。 IASyncResultインターフェイスで保持するかどうかはわかりませんが、このチェックを実行するのと同様の方法があります。あなたのar.AsyncState == nullであることに気付きます。おそらくそこから開始しようとします。つまり、正しく接続するとnullになりますか?

    private void connConnectCompleted(AsyncCompletedEventArgs e) 
    { 
        if (e.Error != null) 
        { 
         // Something didn't work...abort captain 
         CloseSocket(); 
         Console.WriteLine(this.GetType().ToString() + @":Error connecting socket:" + e.Error.Message); 
         return; 
        } 
        // Do stuff with your connection 
    } 
    

    編集:申し訳ありませんが、私はあなたが何をしているかにより関連している、私は私のAsyncCompletedEventArgsを生成したものを投稿していなかった実現しませんでした。あなたはar.AsyncStateがnullであると思っていた理由がわかります。

    private void OnConnect(IAsyncResult asyncResult) 
    { 
        if (OnConnectCompleted == null) return; // Check whether something is using this wrapper 
        AsyncCompletedEventArgs args; 
        try 
        { 
         Socket outSocket = (Socket) asyncResult.AsyncState; 
    
         // Complete connection 
         outSocket.EndConnect(asyncResult); 
    
         args = new AsyncCompletedEventArgs(null); 
         OnConnectCompleted(this, args); 
        } 
        catch (Exception e) 
        { 
         args = new AsyncCompletedEventArgs(e.Message); 
         OnConnectCompleted(this, args); 
        } 
    } 
    
    +0

    AsyncStateは、カスタムデータをコールバックメソッドに渡すために使用されます。私はそのような必要がないので、それはnullです。エラーは発生しません。私はあなたの例を理解していません(不完全です)。 IAsyncResultにはエラーはなく、独自のカスタムメソッドであるため、CloseSocket()メソッドのコードを提供する必要があります。 Othwerise、あなたのコード例がどのように役立つかわかりません。 –

    +0

    CloseSocket()は、いくつかのイベントを起動してプログラムの他の部分に通知し、ソケット上で.Close()を実行します。 – themartinmcfly

    1

    NullReferenceExceptionはおそらくTcpClient.Clientがnullであることによるものです。

    あなたはTcpClient.BeginConnectためMSDN Exampleに従い、状態オブジェクトとしてTcpClientオブジェクトを渡すとしたら:

    private void onConnEst(IAsyncResult ar) 
    { 
         try 
         { 
          TcpClient client = (TcpClient)ar.AsyncState; 
          if(client!=null && client.Client!=null) 
          { 
           client.EndConnect(ar); 
          } 
         } 
         catch(Exception ex){...} 
    } 
    

    これはClose()は、コールバックの前に呼び出された場合に対処する必要があります。

    問題に戻る - アプリケーションが最終的に閉じるまでにどれくらい時間がかかりますか?

    +0

    なぜar.AsyncResultをキャストしますか? ar.AsyncStateを意味しましたか?とにかく、私のクライアントはプライベートなメンバーなので、非同期メソッドに渡す必要はありません。私は現在、TcpClient.Clientがnullであるかどうかを確認することができません(つまり、仕事ではありません)。しかし、私の記憶と以前の経験に基づいて、私がclient.EndConnectを呼び出さなければ、アプリケーションを閉じようとするとアプリケーションはまだハングします。通常、接続タイムアウト(〜20秒)と同じです。接続の試行中にアプリケーションを終了しないと、BeginConnectは同じ時間後に失敗します。 –

    +0

    あなたは正しいですが、 'ar.AsycResult'は' ar.AsyncState'でなければなりません。変更を反映するために編集された投稿。 – zrc210

    +0

    あなたはTcpClientとBeginConnectの構築方法を投稿できますか? BeginConnectの前にソケットをバインドしますか?また、それは重要ではありませんが、どのような.NET Frameworkを使用していますか? – zrc210

    1

    これは明らかにTcpClientクラス内のバグです。私もそれに直面しています。 TcpClient.DisposeはClientフィールドをnullに設定できますが、EndConnectはそれを想定していません。

    +2

    ようこそ!あなたは、バグの詳細をもう少し詳しく説明して、この質問に出くわすかもしれない他の人々のためにあなたの答えをもう少し徹底的にすることを検討したいかもしれません。 –

    0

    これはa know bugです。

    「NullReferenceException」の代わりに「ObjectDisposedException」を受け取る必要があります。

    関連する問題