2011-10-14 27 views
6

Tôi đang cố gắng viết một ứng dụng liên tục tìm kiếm máy chủ lưu trữ trên một lan. Khi tôi chạy điều này như một giao diện điều khiển như đếm ngược.Wait() dường như làm việc tốt. Tuy nhiên khi tôi đưa mã vào một cửa sổ tạo thành đếm ngược.Signal() dường như không làm giảm truy cập của nó. Không chắc vấn đề là gì.Mã không đồng bộ hoạt động trong Bảng điều khiển nhưng không có trong Windows Forms

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Net.NetworkInformation; 
using System.Diagnostics; 
using System.Net; 
using System.Threading; 

namespace Multi_Threaded 
{ 
    public partial class Form1 : Form 
    { 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     PortScanner ps = new PortScanner(); 
     ps.ProbeCompleted += new PingProbeCompleted(ps_ProbeCompleted); 

     ps.run_ping_probe(); 
    } 

    void ps_ProbeCompleted(object sender, PingProbeCompletedArguments e) 
    { 
     MessageBox.Show("I found " + e.ip_adresses_list_of_host.Count.ToString() + "host(s)"); 
    } 
} 

public delegate void PingProbeCompleted(object sender,PingProbeCompletedArguments e); 
public class PingProbeCompletedArguments : EventArgs 
{ 
    public List<string> ip_adresses_list_of_host; 
} 
public class PortScanner 
{ 
    public event PingProbeCompleted ProbeCompleted; 
    static List<string> ip_adresses = new List<string>(); 

    static CountdownEvent countdown; 

    public void run_ping_probe() 
    { 
     ip_adresses.Clear(); 

     countdown = new CountdownEvent(1); 

     string ipBase = "10.125."; 
     for (int sub = 0; sub < 14; sub++) 
     { 
      for (int i = 1; i < 255; i++) 
      { 
       string ip = ipBase + sub.ToString() + "." + i.ToString(); 
       Ping p = new Ping(); 
       p.PingCompleted += new PingCompletedEventHandler(p_PingCompleted); 
       countdown.AddCount(); 
       p.SendAsync(ip, 100, ip); 
      } 
     } 
     countdown.Signal(); 
     countdown.Wait(); 
     PingProbeCompletedArguments e = new PingProbeCompletedArguments(); 
     e.ip_adresses_list_of_host = ip_adresses; 
     ProbeCompleted(this, e); 

    } 

    private void p_PingCompleted(object sender, PingCompletedEventArgs e) 
    { 
     string ip = (string)e.UserState; 
     if (e.Reply.Status == IPStatus.Success) 
     { 
      ip_adresses.Add(ip + "\t" + e.Reply.RoundtripTime + " ms"); 
     } 
     countdown.Signal(); 
    } 
} 

Trả lời

0

Trình xử lý chờ đợi của bạn được chạy dưới một luồng từ threadpool. bạn cần để có được trở lại vào thread UI đã UI được cập nhật (do vòng lặp thông điệp rằng giao diện người dùng chạy trên) - cho rằng bạn sử dụng SynchronizationContext

đây biết thêm về cách bạn nó: http://www.codeproject.com/KB/threads/SynchronizationContext.aspx

6

Có, mã lỗi của bạn khi bạn sử dụng nó trong một dự án Winforms. Vấn đề là lớp Ping tạo ra một nỗ lực tốt nhất để nâng cao sự kiện PingCompleted trên cùng một luồng được gọi là SendAsync(). Nó sử dụng phương thức AsyncOperationManager.CreateOperation() để làm như vậy.

Sự cố là thực sự hoạt động trong ứng dụng Winforms. Nó cố gắng nâng cao sự kiện trên chuỗi chính. Nhưng điều đó không thể hoạt động kể từ khi bạn chặn chủ đề chính với cuộc gọi đếm ngược.Wait(). Ping không thể hoàn thành vì chủ đề chính bị chặn. Chủ đề chính không thể hoàn thành vì ping không hoàn thành. Thành phố bế tắc.

Nó hoạt động trong một ứng dụng chế độ điều khiển vì nó không có một nhà cung cấp đồng bộ như Winforms làm. Sự kiện PingComplete sẽ được nâng lên trên một thread threadpool.

Chặn chuỗi giao diện người dùng về cơ bản là thiếu sót. Sửa lỗi nhanh là chạy mã trên chuỗi công nhân. Cẩn thận rằng điều này làm cho sự kiện ProbeCompleted cũng được kích hoạt trên nhân viên đó. Sử dụng Control.BeginInvoke() để sắp xếp nó vào chuỗi giao diện người dùng. Hoặc sử dụng BackgroundWorker.

private void Form1_Load(object sender, EventArgs e) { 
     PortScanner ps = new PortScanner(); 
     ps.ProbeCompleted += new PingProbeCompleted(ps_ProbeCompleted); 
     ThreadPool.QueueUserWorkItem((w) => ps.run_ping_probe()); 
    } 

Và đừng quên xóa thêm lệnh Signal().

Các vấn đề liên quan