利用UdpClient.Receive方法接收到数据后,弹出一个新的窗体,必须得是form.Show()出来的窗体,结果这个新出来后就不动了,这个线程死在这里了。我估计是国为UdpClient.Receive方法是阻塞方式,所以才会这样,可我搞了好久也没找到解决办法,利用异步处理也没成功,不知是我写的不对还是根本不行,请大家一起找找解决办法。

解决方案 »

  1.   

    这是那个函数,是新开的一个线程调用的,大家看看
    private  void StartListener() 
    {
    Thread.Sleep(2000);
    RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, GroupPort);
    while(true)
    {
    try
    {
    Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);  string returnData = Encoding.UTF8.GetString(receiveBytes); Form2 myForm=new Form2();
    myForm.Show();
    Application.DoEvents();
                      //到这里,新窗体出来后就死在那里,一关,整个程序都关了
    }
    catch
    {
    }
    }
    }
      

  2.   

    wlhardnet(牧羊人) .结贴再给你分
      

  3.   

    myForm.Show();的方法最好挂在主线程上
      

  4.   

    myForm.Show();的方法在主线程上挂不了吧?
      

  5.   

    同意RedComet
    LZ的模型错了。当你在接受线程show()新窗口后再次回到while(true)去执行阻塞的Recieve()动作。而你Show()出来的Form是[STA]的,也就是强制单线程。这就意味着该Form的消息泵是在你的接受线程运行的。由于该线程被Recieve()阻塞了,所以新Form无法作消息循环,当然没响应。合理的做法是当接受线程受到udp包时通过委托机制通知UI主线程,需要的话将接受到的内容一并发送给UI线程。然后由UI线程负责new Form。整个模型的关键在于线程通信
      

  6.   

    从你的代码里看不出怎么死的?
    还有你Form2.Show()是干吗的,不会显示一个空窗体吧,我想在你的Form2 的load或者其它事件里还有处理语句,检查一下看看呐
      

  7.   

    JadyWang(最近比较矛盾) :
    你应该是讲到点子上了,可我对线程间的通讯却不清楚,能否就你上述所说的给个简单的例子?
      

  8.   

    如果你只需要做多线程的窗体控件,那么看这个例子足够了,不过有点繁琐,耐心点(我看了2个小时……):
    ms-help://MS.MSDNQTR.2003FEB.2052/cpguide/html/cpcondevelopingmultithreadedwindowsformscontrol.htm如果你需要一般的多线程通讯,可以去搜索“实现IAsynchronizeInvoke接口”,有关代码我自己也没仔细看,不敢乱发
      

  9.   

    JadyWang(最近比较矛盾) :你说的那个代码真够NB的,看来我今天下午不能干其它事了
      

  10.   

    呵呵,怕麻烦看这个吧。我写过一个udp监听的control,完全跟着上面的例子写的,有所简化。不过很简陋,有错误大家指正。
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Windows.Forms;
    using System.Net.Sockets;
    using System.Threading;
    using System.Net;
    using System.Text;namespace EasyUdp
    {
    /// <summary>
    /// 用作onRecv事件的参数的类
    /// </summary>
    /// <permission cref="EasyUdp">Public Class</permission>
    public class EasyUdpRecvCtlEventArgs //: EventArgs
    {
    /// <summary>
    /// 包含发送Udp数据报的远端主机的IP
    /// </summary>
    /// <permission cref="EasyUdp.EasyRecvCtlEventArgs">Private Member</permission>
    private string remoteIP; public string RemoteIP
    {
    get
    {
    return this.remoteIP;
    }
    }
    private string recvStr;
    public string RecvStr
    {
    get
    {
    return this.recvStr;
    }
    } /// <summary>
    /// EasyUdpRecvCtlEventArgs的构造函数
    /// </summary>
    /// <param name="remoteIP">发送Udp数据报的远端主机的IP</param>
    /// <param name="recvStr">接收到的字符串</param>
    public EasyUdpRecvCtlEventArgs(string remoteIP,string recvStr)
    {
    this.recvStr = recvStr;
    this.remoteIP = remoteIP;
    } } /// <summary>
    /// UserControl1 的摘要说明。
    /// </summary>
    public class EasyUdpRecvCtl : System.Windows.Forms.Control
    {
    //private EventHandler onRecvHandler; //public event EventHandler onRecv; public delegate void OnRecvHandler(object Sender,EasyUdpRecvCtlEventArgs e);
    private OnRecvHandler onRecvHandler; public event OnRecvHandler onRecv; private UdpClient udpReceiver; private Thread hearkenThread; private byte[] recvBytes = new byte[500];
    private string recvStr; private Encoding encoder = Encoding.Unicode;
    private int localPort;
    public int LocalPort
    {
    get
    {
    return localPort;
    }
    set
    {
    localPort = value;
    }
    }
    /// <summary>
    /// 必需的设计器变量。
    /// </summary>
    private System.ComponentModel.Container components = null; public EasyUdpRecvCtl(int local_Port)
    {
    // 该调用是 Windows.Forms 窗体设计器所必需的。
    InitializeComponent(); //初始化UdpReceiver将其绑定到localPort端口
    this.localPort = local_Port;
    if(this.DesignMode == false)
    {
    try
    {
    this.udpReceiver = new UdpClient(this.localPort);
    }
    catch(Exception e)
    {
    MessageBox.Show(e.ToString());
    throw new Exception("端口已被占用!");
    }
    }
    // TODO: 在 InitComponent 调用后添加任何初始化
    this.onRecvHandler = new OnRecvHandler(OnRecv);
    } public EasyUdpRecvCtl()
    {
    // 该调用是 Windows.Forms 窗体设计器所必需的。
    InitializeComponent(); //初始化UdpReceiver将其绑定到localPort端口
    if(this.DesignMode == false)
    {
    this.localPort = 10000;
    try
    {
    this.udpReceiver = new UdpClient(this.localPort);
    }
    catch(Exception e)
    {
    MessageBox.Show(e.ToString());
    }
    } // TODO: 在 InitComponent 调用后添加任何初始化
    this.onRecvHandler = new OnRecvHandler(OnRecv);
    } /// <summary>
    /// 清理所有正在使用的资源。
    /// </summary>
    protected override void Dispose( bool disposing )
    {
    if( disposing )
    {
    if( components != null )
    components.Dispose();
    }
    base.Dispose( disposing ); //关闭udpReceiver
    //this.udpReceiver.Close();
    } #region 组件设计器生成的代码
    /// <summary>
    /// 设计器支持所需的方法 - 不要使用代码编辑器 
    /// 修改此方法的内容。
    /// </summary>
    private void InitializeComponent()
    {
    components = new System.ComponentModel.Container();
    }
    #endregion protected override void OnHandleCreated(EventArgs e)
    {
    base.OnHandleCreated (e); //初始化侦听线程开始侦听
    this.hearkenThread = new Thread(new ThreadStart(HearkenProc));
    this.hearkenThread.Start(); } protected override void OnHandleDestroyed(EventArgs e)
    {
    //销毁侦听线程
    this.hearkenThread.Abort();
    //this.hearkenThread.Join();
    //关闭udpReceiver
    this.udpReceiver.Close(); base.OnHandleDestroyed (e);
    } private void OnRecv(object Sender,EasyUdpRecvCtlEventArgs e)
    {
    this.onRecv(Sender,e);
    } private void HearkenProc()
    {
    //只侦听对方10001端口发到本机的Udp包
    IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any,10001); while(true)
    {
    this.recvBytes = this.udpReceiver.Receive(ref remoteIPEndPoint);
    this.recvStr = this.encoder.GetString(recvBytes); //收到数据报后跨线程(向控件主线程)激发事件onRecvHandler
    //将收到的数据和对方IP发回主线程
    this.BeginInvoke(this.onRecvHandler,
    new object[]{
    this,
    new EasyUdpRecvCtlEventArgs(remoteIPEndPoint.Address.ToString(),recvStr)
    });
    }
    }
    }
    }