是这样的,我做了一个C/S架构的客户端和服务器,各自开了一个线程,并有各自的线程调用函数来接受消息
但现在有个需求是
1.服务器发送一个特定命令给客户端,客户端要new一个我自己写的窗体,并show出来,这时候show出来会卡死
2. 在1中说的那个窗体是纯粹没有任何操作的窗体,现在我还想窗体一show出来,里面又开了个线程!求解
3. 我用网友说的new Application(窗体对象); 我发现这样可以正常show出来,新窗体开的新线程可以正常执行,但是它的父窗体中的线程调用函数会停止执行,直到我这个新窗体关闭为止!!!百思不得其解,特发此贴,希望牛人可以来帮忙下!无关紧要的不给分!

解决方案 »

  1.   

    设置线程为STA的,然后启动,WinForm下的窗口是必须运行在STA模式下面的:System.Threading.Thread tmp = new System.Threading.Thread(show);
    tmp.SetApartmentState(System.Threading.ApartmentState.STA);
    tmp.Start();
      

  2.   

    Show这个方法执行完之后会立即返回,新窗体本身没有消息循环,windows将消息发送给创建它的线程,线程结束后,失去了消息循环,窗体自然也会消失。
    在线程中新打开的窗体可以使用ShowDialog,这个方法打开的窗体有自己的消息循环,所以这个函数在窗体被主动关闭之前是不会返回的。因为是在新线程中打开的,该窗体并不影响“父”窗体响应鼠标和键盘,它们是两个并行的消息循环。
    在线程中新打开窗体也可以使用Application.Run,这个同样也是会为新窗体建立消息循环。
      

  3.   

    还有第三种方法,和一楼的方法类似,就是在线程中向主窗体的UI线程发送消息,使用主窗体UI线程打开新窗体。在.net中就是使用主窗体UI的Invoke或者BeginInvoke方法。
      

  4.   

    3楼说的通过消息发送到主窗体,让主窗体的UI线程来处理新的Form,这样不会出现卡的问题!
      

  5.   


    关键是,用你这种方法不卡,但能不能两个窗体继续接受消息呢..我发现我用Application.Run, show出来的那个窗体可以接受消息,但父窗口是不行的!
      

  6.   

    123楼四种方法都不影响父窗体和子窗体接受各自的消息。但要注意Application.Run和ShowDialog两个方法都会一直阻塞,因为它们本身在维持一个循环。所以在这两个方法后面的代码,在新窗体运行期间是不会处理的,要放在前面。在主线程中操作新窗体没有问题。
      

  7.   

    选用Application.Run来做一个例子:    static class Program
        {
            public static Form1 fm;
            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                fm = new Form1();
                Application.Run(fm);
            }
        }    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }        private void button1_Click(object sender, EventArgs e)
            {
                Thread t = new Thread(test);
                t.Start();
            }
            void test()
            {
                Form2 fm = new Form2();
                Application.Run(fm);
            }
        }    public partial class Form2 : Form
        {
            bool close = false;
            public Form2()
            {
                InitializeComponent();
            }        private void Form2_Load(object sender, EventArgs e)
            {
                System.Threading.Thread t = new System.Threading.Thread(test);
                t.Start();
            }
            protected override void OnClosed(EventArgs e)
            {
                close = true;
            }
            void test()
            {
                int i = 0;
                while(!close)
                {
                    i++;
                    Program.fm.Invoke(new Action(() => { Program.fm.textBox1.Text = i.ToString(); }));
                    System.Threading.Thread.Sleep(100);
                }
            }
        }
      

  8.   

    你这样说...我不能用Application.Run和 ShowDialog咯,这样都阻塞了
    希望你好好看看我下面的代码,理解我的意思吧,然后给我段代码我参考下行么?
    这样的 我现在有个主线程
    Thread MainThread = new Thread(new ThreadStart(MainMethod));
    MainThread.Start();void MainMethod()
    {
         //接受服务端发来的命令
          if (命令符合)
         {
            //NewForm表示一个新的窗体,里面Load的时候开启了自己的线程,和执行自己的线程函数
            NewForm dlg = new NewForm();  
            //dlg.show();   //这种情况直接卡死
             //dlg.showDialog(); //也是直接卡死
             Application.Run(dlg); //这种情况可以开启新窗体,也可以执行新窗体的线程函数,但是
                                      //父窗体的MainMethod这个线程函数不会再执行了,之后服务端发的                                //命令都没办法接受到
                  }}
      

  9.   

    把你的项目拿来,我给你重写。(为什么我会上火呢?)
     “Application.Run(dlg); //这种情况可以开启新窗体,也可以执行新窗体的线程函数,但是
      //父窗体的MainMethod这个线程函数不会再执行了,之后服务端发的 //命令都没办法接受到”
    你这段话的第二行,是不是在执行什么操作?你应该看懂6、2楼在说什么,再考虑你的错误发生在哪里。此问题到此为止,不再回复。别给我分,我嫌恶心。
      

  10.   

    Application.Run(dlg); //这种情况可以开启新窗体,也可以执行新窗体的线程函数
    LZ,这里你的代码改成
    this.Invoke(new Action(() => { dlg.show(); }));
    这样就可以了啊.....
    我最近做个小项目,我是这样的,确实可以!