none
求助关于C#多线程 RRS feed

  • 问题

  • 刚学C#没多久,听朋友说这个论坛藏龙卧虎,并且都是热心肠,遇到一些问题,恳请各位大哥指教,问题如下:

    程序启动时候同时打开若干个子窗体(个数有可能每次不一样),并且每个窗体都运行于不同的线程中,当主程序接收到某一指令之后如何才能发送指令给这些窗体执行某一项任务呢?比如我需要通知一号窗体增加一个控件,通知3号窗体隐藏,4号显示等等……

     

    我该如何实现?问题比较多,还望各位大哥指教,越详细越好,先谢谢了~!

    2010年7月9日 9:49

答案

  • 你好!

         如果你一定要多线程,那可以每次显示窗体的时候都开启一个新线程,新线程中可以使用:Application . Run(new  Form2 ());来启动新窗体,不然新窗体将马上关闭。各线程之间通信,可以使用事件,信号量等同步机制。

         实际上我认为你的需求不需要多线程,你使用自定义的简单事件,足可以实现各个窗体之间交互了!

     


    周雪峰
    2010年7月10日 5:35
    版主
  • 他们的办法都很复杂,我告诉你一个简单方法,用委托。

    把你的每个Form都当着一个类来看待,然后需要UI线程的操作都作为委托公开,

    你在主进程中把你的Form变量都保存起来,然后做成静态全局共享,比如用字典类,这样通过名称就可以在任何窗体中去找到任何一个Form.

    2010年7月10日 6:02
  • 1.主窗体收集所有子窗体的引用。
    2.子窗体提供方法和该方法的Delegate。
    3.主窗体通过Delegate访问。

    例:

    主窗体:
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private Form2 form2;
            private void Form1_Load(object sender, EventArgs e)
            {
                form2 = new Form2();
                form2.Show();
            }
            private void button1_Click(object sender, EventArgs e)
            {
                Form2.Delegate1 d1 = new Form2.Delegate1(form2.WriteText);
                d1.Invoke(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            }
        }

    子窗体:
        public partial class Form2 : Form
        {
            public delegate void Delegate1(string text);
            public void WriteText(string text)
            {
                textBox1.Text = text;
            }
            public Form2()
            {
                InitializeComponent();
            }
        }

    说明:跨线程也可以这么调用。

    2010年7月11日 6:17

全部回复

  • 首先说明一点,就是 .NET 中的 Windows Forms 窗体总是运行在 UI 线程上,而不是多线程环境。

    关于窗体间传递消息的问题,我写过一篇博客,有人也有转载的。主要的,也是比较好的方法就是通过事件订阅来实现。参考 http://kb.cnblogs.com/a/1443412/ (hustorochi 的回帖)


    Mark Zhou
    2010年7月9日 10:34
  • 回楼上,不同窗体是可以运行在不同的线程中的

    2010年7月9日 12:32
  • 首先说明一点,就是 .NET 中的 Windows Forms 窗体总是运行在 UI 线程上,而不是多线程环境。

    关于窗体间传递消息的问题,我写过一篇博客,有人也有转载的。主要的,也是比较好的方法就是通过事件订阅来实现。参考 http://kb.cnblogs.com/a/1443412/ (hustorochi 的回帖)


    Mark Zhou

    其实WinForm是可以多线程的,可以在新线程中用

    Application.Run(new Form2());

    来启动窗口消息循环。而且,要同时启动多个顶级窗口的话,必须是在不同的线程中。

    如果是这种情况,窗口间交互时必须注意线程同步问题。

    当然一般来说用mazhou的方法是比较合适的。


    Tech Blog: http://gildor.cnblogs.com
    2010年7月9日 12:56
  • 我的问题还没解决呢,我的项目中有Form1,Form2两个窗体,

    我在Form1中这样写

    private List<Form2> formList;
    private void Form1_Load(object sender, EventArgs e)
        {
           formList = new List<Form2>();
           formList.add(new Form2());
           formList.add(new Form2());
           formList.add(new Form2());
           formList.add(new Form2());
           formList.add(new Form2());
           for(int i=0;i<formList.Count;i++)
           {
              formList[i].Show();
           }
        }
    

    我该如何通知不同的窗体执行不同的任务呢?并且每个窗体执行任务的时候主窗体跟其他窗体都不能失去响应,我开始是直接在Form2中定义了很多个不同的方法来操作Form2中的几个控件,比如Form2中有一个Label控件,我用timer控制它在窗体中循环滚动,当多个窗体都执行这一动作的时候其他窗体就失去了响应,类似于假死状态,我想要每个窗体上面的操作都不能影响其他窗体的运行,各位大哥帮帮我吧,最好能有示例代码。

    2010年7月10日 4:53
  • 你好!

         如果你一定要多线程,那可以每次显示窗体的时候都开启一个新线程,新线程中可以使用:Application . Run(new  Form2 ());来启动新窗体,不然新窗体将马上关闭。各线程之间通信,可以使用事件,信号量等同步机制。

         实际上我认为你的需求不需要多线程,你使用自定义的简单事件,足可以实现各个窗体之间交互了!

     


    周雪峰
    2010年7月10日 5:35
    版主
  • 他们的办法都很复杂,我告诉你一个简单方法,用委托。

    把你的每个Form都当着一个类来看待,然后需要UI线程的操作都作为委托公开,

    你在主进程中把你的Form变量都保存起来,然后做成静态全局共享,比如用字典类,这样通过名称就可以在任何窗体中去找到任何一个Form.

    2010年7月10日 6:02
  • 你好!Galactica!

         我也建议他使用事件了,和你的方法类似,我个人感觉使用事件更加的严谨。


    周雪峰
    2010年7月10日 6:40
    版主
  • 1.主窗体收集所有子窗体的引用。
    2.子窗体提供方法和该方法的Delegate。
    3.主窗体通过Delegate访问。

    例:

    主窗体:
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private Form2 form2;
            private void Form1_Load(object sender, EventArgs e)
            {
                form2 = new Form2();
                form2.Show();
            }
            private void button1_Click(object sender, EventArgs e)
            {
                Form2.Delegate1 d1 = new Form2.Delegate1(form2.WriteText);
                d1.Invoke(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            }
        }

    子窗体:
        public partial class Form2 : Form
        {
            public delegate void Delegate1(string text);
            public void WriteText(string text)
            {
                textBox1.Text = text;
            }
            public Form2()
            {
                InitializeComponent();
            }
        }

    说明:跨线程也可以这么调用。

    2010年7月11日 6:17