2011-11-11 68 views
0

當我使用F11調試,NetStatustrue,但是當我使用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之前觸發...但是當您只是運行代碼時,您會在定時器丟棄之前處理該定時器有機會開火。此外,您在撥打CheckIp後立即使用conn.Connected的值 - 因此,如果計時器確實觸發了,則可能是在您檢查了值之後。

我會強烈建議您只做同步檢查。得到這個工作,然後然後考慮一種異步方法。

+0

我明白了!我添加Thread.Sleep(300);在conn.Connected之前,添加Thread.Sleep(2000);之前_timer.Dispose();現在,這是工作!謝謝! – flyingnn

+1

@flyingnn:雖然這不是一個好的解決方案。這基本上是檢查連接的緩慢和不可靠的方式......正如我所說,我強烈建議使用同步方法,除非您真的想要正確執行異步方法*。用'Sleep'調用代碼來代碼是不是一個獲得可靠系統的好方法。 –

+0

我是C#初學者。我想在連接到它的SQL端口之前檢查目標主機的網絡狀態。否則,當SQL SERVER關閉時,用戶將等待20-30S。 – flyingnn

0

你創建了一個定時器,它在線程池上執行一個函數 - 所以你沒有太多的保證,當CheckIP返回定時器回調已經執行。

此外:爲什麼你創建它後立即處理定時器?雖然MSDN指出可以在處理之後發生回調,因爲回調是排隊的,這當然是一種不好的風格。這也意味着你只需要檢查一次 - 所以你可以同步執行 - 尤其是wait_conn表示它應該等到連接建立完成。

另外:TcpClient是一次性的,所以你應該做的:

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

存在具有類的成員變量,如果你不使用它做什麼反正是沒有意義的。