2017-03-29 3 views
1

次の方法でスレッドのポートをリッスンします。 WaitOneメソッドで待機している間、私はスレッドを停止します(私はIsCancellationRequestedを真にしています)。listenerオブジェクトを閉じることができません。それから私は同じポートを聞きたいときにエラーが発生します。スレッドを停止した後、変数でリスン操作をキャンセルできますか?

リスナーオブジェクトを変数にバインドできますか?その変数がfalseの場合、自動シャットダウンを行います。

スレッドが別のスレッドで停止していることを確認したくない場合は、listenerを閉じてください。

public void StartListening(Connection connection) 
{ 
    // There are codes here.. 
    try 
    { 
     listener.Bind(localEndPoint); 
     listener.Listen(2); 

     while (connection.CancellationTokenSource.IsCancellationRequested == false) 
     {     
      allDone.Reset();      
      listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 
      allDone.WaitOne(); // While I'm waiting here, I'm making the 'IsCancellationRequested' variable true. 
     } 

     listener.Close(); 
    } 
    catch (Exception e) 
    { 
     // There are codes here.. 
    } 

    // There are codes here.. 
} 

注:Connectionクラスは、私はそれがSystem.Threading.CancellationTokenSource CancellationTokenSourceプロパティが含まれて作成したクラスです。

+0

「listener.Close();」をfinallyブロックに入れることができます。しかしそれはテープソリューションです。スレッドを終了するのは恐ろしい解決策です。 –

答えて

1

私は

次の2つのハンドルで待機して試みることができるconnectionの正確な構造を知っているが、...しないでください。 (未テスト)

var handles = new EventWaitHandle[] 
{ 
    allDone, 
    connection.CancellationTokenSource.Token.WaitHandle 
}; 

int index = EventWaitHandle.WaitAny(handles); 

WAITANYはwaithandle WHOISセットのインデックスを返します。だからあなたが中断したいかどうかを決定してください。


メイビー何かのように:リスナーをキャンセルする

public void StartListening(Connection connection) 
{ 
    // There are codes here.. 
    try 
    { 
     listener.Bind(localEndPoint); 
     listener.Listen(2); 

     var handles = new EventWaitHandle[] 
     { 
      allDone, 
      connection.CancellationTokenSource.Token.WaitHandle 
     }; 

     do 
     {     
      allDone.Reset();      
      listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 
     } 
     while(EventWaitHandle.WaitAny(handles) == 0); 

     listener.Close(); 
    } 
    catch (Exception e) 
    { 
     // There are codes here.. 
    } 

    // There are codes here.. 
} 

方法。現時点では何か面白いことをすることはできません。誰かがより良い方法を持っている場合は、気軽にご利用ください;-)

ManualResetEvent _listenerTerminated = new ManualResetEvent(false); 

// <snip> 

listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 

private void AcceptCallback(IAsyncResult ar) 
{ 
    // before calling EndAccept, check an event. 
    if(_listenerTerminated.WaitOne(0)) 
     return; 

    var clientSocket = listener.EndAccept(asyncResult); 
} 

// <snip> 

do 
{     
    allDone.Reset();      
    listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 
} 
while(EventWaitHandle.WaitAny(handles) == 0); 

_listenerTerminated.Set(); 

listener.Close(); 
+0

私はそれがコメントのように複雑だったので、答えを書く必要がありました。それを確認できますか? – Cer

0

これは答えではありません。コメントがあまりにも多いので、私はこのように書いています。

@JeroenvanLangenは、答えをありがとう:

私はEventWaitHandleクラス(暗黙的)にconnection.CancellationTokenSource.Token.WaitHandleオブジェクトを変換する必要があります。私が望むように機能しましたが、EndAcceptプロセスでは、リスナーオブジェクトが破棄されたというエラーが発生しました。

var handles = new EventWaitHandle[] 
{ 
    allDone, 
    Connection.CancellationTokenSource.Token.WaitHandle as EventWaitHandle // Implicitly cast 
}; 
  1. ソリューションと私の解決策との違いは何ですか?
  2. が処分されているため、Listenerオブジェクトが使用されている場所を確認する必要がありますか?
+0

あなたのソリューションと私の違いは、私のソリューションはallDoneだけを待つのではなく、両方のハンドルを待つことです。 'EndAccept'を取り消す方法の例を更新します。 –

+1

' as EventWaitHandle'を使ったキャスティングはここではお勧めできません。コンパイル時には '(EventWaitHandle)Connection.CancellationTokenSource.Token.WaitHandle'を使用してください。 –

+0

私は理解しています。ご協力いただきありがとうございます。 – Cer

0

次のようにIは、

public void StartListening(Connection connection) 
{ 
    // There are codes here.. 
    try 
    { 
     listener.Bind(localEndPoint); 
     listener.Listen(2); 

     var handles = new EventWaitHandle[] 
     { 
      allDone, 
      connection.CancellationTokenSource.Token.WaitHandle 
     }; 

     do 
     {     
      allDone.Reset(); 
      listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 
     } 
     while(EventWaitHandle.WaitAny(handles) == 0); 

     listener.Close(); 
    } 
    catch (Exception e) 
    { 
     // There are codes here.. 
    } 

    // There are codes here.. 
} 

の問題を解決し、私はhandleWaitAnyの方法に信号を送りました。私はこのようにリスニング・プロセスを終了できます。 handleWaitAnyメソッドに信号を送りました。私はこのようにリスニング・プロセスを終了できます。しかし、私は接続されたclientsに対処しなければならなかった。私はこれを次のようにしました。

private void AcceptCallback(IAsyncResult ar) 
{ 
    if (Connection.CancellationTokenSource.IsCancellationRequested == true) 
    { 
     return; 
    } 

    // There are codes here.. 
} 

private void ReadCallback(IAsyncResult ar) 
{ 
    StateObject state = (StateObject)ar.AsyncState; 
    Socket handler = state.workSocket; 

    if (Connection.CancellationTokenSource.IsCancellationRequested == true) 
    { 
     handler.Close(); // Client connections closed 
     return; 
    } 

    // There are codes here.. 
} 
関連する問題