2011-11-11 12 views
0

私はF11デバッグを使用すると、NetStatus値はtrueですが、私はF5デバッグを使用する場合、NetStatus値はfalseです。どうして?どうすれば修正できますか?C#TimerCallback戻り値エラー

_connectの値が何時変わるか分かりません。 これはマルチスレッド同期の問題ですか?

namespace conn 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Net; 
    using System.Net.Sockets; 
    using System.Threading; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      wait_conn(); 
     } 

     private static void wait_conn() 
     { 
      bool NetStatus = false; 
      string DataS = "127.0.0.1"; 

      CheckIpConn conn = new CheckIpConn(); 
      conn.CheckIp(DataS); 

      //Thread.Sleep(3000); 
      NetStatus = conn.Connected; 

      if (!NetStatus) 
       Console.WriteLine(conn.Connected.ToString()); 

      Console.Read(); 
     } 
    } 

    public class CheckIpConn 
    { 
     private int _port = 135; 
     private volatile bool _connect; 
     private IPEndPoint _iPEndPoint; 
     private TcpClient _client; 
     private TimerCallback _timerCallBack; 
     private System.Threading.Timer _timer; 

     public bool Connected 
     { 
      get { return _connect; } 
     } 

     public void CheckIp(string Ip) 
     { 
      _iPEndPoint = new IPEndPoint(IPAddress.Parse(Ip), _port); 
      _timerCallBack = new TimerCallback(CheckConnect); 
      _timer = new System.Threading.Timer(_timerCallBack, null, 10, 1000); 
      _timer.Dispose(); 
     } 

     public void CheckConnect(object o) 
     { 
      try 
      { 
       _client = new TcpClient(); 
       _client.Connect(_iPEndPoint); 
       _connect = true; 
       _client.Close(); 
      } 
      catch 
      { 
       _connect = false; 
      } 
     } 
    } 
} 

答えて

1

あなたのコードは極めて不明である - あなたが非同期的に物事をやろうとしているが、ひどいので、やっているように見えます。たとえば、Timerを作成してからすぐにを処理するとします。

Disposeコールの前にタイマーが起動する可能性があるため、デバッガで1行ずつステップ実行すると...しかし、コードを実行するだけで、タイマーが終了する前に処分されます火災のチャンス。さらに、CheckIpを呼び出した直後にconn.Connectedの値を使用しています。したがって、というタイマーが起動した場合は、が発砲したと考えられます。

私はを強くにしてください。あなたはちょうど同期してチェックをすることをお勧めします。それを稼働させて、次にを非同期的なアプローチと考えてください。

+0

私は見る!私はThread.Sleep(300)を追加します。 conn.Connectedの前に、Thread.Sleep(2000)を追加します。 before _timer.Dispose();今、それは仕事です!ありがとうございます! – flyingnn

+1

@flyingnn:それは良い解決策ではありません。それは基本的に接続をチェックするのが遅く信頼できない方法です...私が言ったように、あなたは本当に非同期的なアプローチ*を適切にしたいのでなければ、同期アプローチを使うことを強く勧めます。 'Sleep'呼び出しでコードをペーストすることは、信頼できるシステムに到達する良い方法ではありません。 –

+0

私はC#初心者です。私はそれがSQLポートに接続する前に、ターゲットのホストのネットワークの状態を確認したい。それ以外の場合、SQL SERVERがダウンすると、ユーザーは20-30秒待機します。 – flyingnn

0

スレッドプール上で関数を実行するタイマーを作成します。したがって、CheckIPがタイマーコールバックが返されたときに、実質的に多くの保証を持たないようにします。

さらに、タイマーを作成したらすぐに処分するのはなぜですか? MSDNは、コールバックがキューに入れられているためにdispose後にコールバックが発生する可能性があると述べていますが、これは確かに悪いスタイルです。また、これはあなたが一度だけチェックしていることを意味しています - それで、あなたはそれを同期的に行うかもしれません - 特にwait_connは、接続が確立されるまで待つべきであることを示します。

using (var client = new TcpClient()) 
{ 
    client.Connect(_iPEndPoint); 
    _connect = true; 
    client.Close(); 
} 

あなたはとにかくそれで何もしない場合は、クラスのメンバ変数を持つはポイントがありません。また

:あなたが行う必要がありますのでTcpClientは使い捨てです。