none
C#多线程问题 RRS feed

  • 问题

  • 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.Threading;
    namespace StartThread
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            public delegate void mydelegate();
            private void button1_Click(object sender, EventArgs e)
            {            
                Thread nonParameterThread = new Thread(new ThreadStart(NonParameterRun));
                nonParameterThread.IsBackground = true;
                nonParameterThread.Start();
                for (int j = 0; j < 10; j++)
                {
                    string str2 = "";
                    str2 += j;
                    label1.Text = str2;
                    label1.Refresh();
                    System.Threading.Thread.Sleep(300);
                }
            }
            public void stop() {
                for (int z = 0; z < 10; z++)
                {
                    string str = "";
                    str += z;
                    label2.Text = str;
                    label2.Refresh();
                    System.Threading.Thread.Sleep(200);
           
                }
            }
            private void NonParameterRun()
            {           
                button1.BeginInvoke(new mydelegate(stop));    
                
            }
        }
    }
    各位大虾,我想请问下 System.Threading.Thread.Sleep(300);应该是让主线程阻塞300毫秒,然后可以让nonParameterThread这个线程得以执行;但是为什么程序执行起来确是主线程执行完毕后,nonParameterThread这个线程才开始执行?谢谢各位
    2012年1月5日 9:30

答案

  • 我的想法是:label1.Text 的内容变成0,接着label2.Text的内容变成0,然后label1.Text变为1,接着label2.Text变为1.。。。。。。这样轮着来~~~,不知道这样多线程能不能实现~~~多谢大家~~~

    你不是一开是说“同时变化吗”?你到底要什么啊?怎么现在又变成了“先后变化”???有图为证:

    同时变化就是我第一次回帖的那段代码,完全没有错误,至少在我这里。

    至于异步,你完全可以参考我这样的代码(你可以拷贝我下面代码,覆盖我发给你的文件)

    namespace WinFormCSharp
    {
        public partial class Form1 : Form
        {
            private static Mutex m = new Mutex(false"MyMutex");
            private static object obj = new object();
            public Form1()
            {
                InitializeComponent();
            }
     
            public delegate void mydelegate();
            private void button1_Click(object sender, EventArgs e)
            {
                Thread nonParameterThread1 = new Thread(new ThreadStart(button1Change));
                nonParameterThread1.IsBackground = true;
                nonParameterThread1.Start();
     
                Thread nonParameterThread2 = new Thread(new ThreadStart(button2Change));
                nonParameterThread2.IsBackground = true;
                nonParameterThread2.Start();
            }
            public void button2Change()
            {
                for (int z = 0; z < 10; z++)
                {
                    lock (obj)
                    {
                        m.WaitOne();
                        label2.Text = z.ToString();
                        label2.Refresh();
                        m.ReleaseMutex();
                        Thread.Sleep(500);
                    }
                }
            }
     
            public void button1Change()
            {
                for (int z = 0; z < 10; z++)
                {
                    lock (obj)
                    {
                        m.WaitOne();
                        label1.Text = z.ToString();
                        label1.Refresh();
                        m.ReleaseMutex();
                        Thread.Sleep(500);
                    }
                  
                }
            }
     
            private void Form1_Load(object sender, EventArgs e)
            {
     
            }
     
        }
    }

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处
    2012年1月7日 4:32
    版主
  • 如果你确定线程只操作这些控件,最简单的方法——设置CheckForIllegalCrossThreadCalls=False(在构造函数的InitializeComponent()后边,把每一个控件的这个属性设置为False就可以了)
       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处
    • 已标记为答案 klvchen 2012年1月9日 3:37
    2012年1月9日 2:54
    版主

全部回复

  • 你在nonParameterThread 这个自己创建的线程中调用了 button1.BeginInvoke方法,这个方法是一个异步调用,所以mydelegate指向的方法不会等执行完就会返回,然后NonParameterRun又没有其他的代码需要执行所以nonParameterThread 很快就结束了。当然这还不是重点,你调用了button1.BeginInvoke,说明你知道不能在非UI线程中去访问操作UI线程所创建的控件。那么BeginInvoke调用了之后就会把mydelegate指向的方法作为一个消息指派给UI线程,让它去执行。但是此时UI线程就是主线程,一个线程不可能同时执行两件事情,所以它不可能又执行下面的for循环又执行mydelegate指向的方法,只会按顺序来。
    AndersTan
    2012年1月6日 2:09
  • 那我想同时发生这两件事,是不是应该把for循环的代码放入NonParameterRun中?我试了一下也不行啊,感觉多线程好难~~~

    2012年1月6日 2:45
  • 要同时发生两件事情就让两个不同的线程去执行,一个线程不可能同时做两件事情。你自己想啊,你又要主线程休眠同时又要让他干活,怎么可能呢。另外UI线程(在你的代码中UI线程就是主线程)要少干活,要让它保持界面的响应。你想要干什么,你先描述一下。
    AndersTan
    2012年1月6日 3:05
  • 我想利用多线程的方法,点击button1,让 label1.Text和 label2.Text同时发生变化。谢谢~~
    2012年1月6日 7:47
  • 我的想法是这样的,用主线程来改变 label1.Text,用nonParameterThread线程来改变label2.Text.不知道我这种想法可不可以实现~~~~~
    2012年1月6日 7:50
  • 我想利用多线程的方法,点击button1,让 label1.Text和 label2.Text同时发生变化。谢谢~~

    1)设计界面:

    2)按钮事件:

    namespace WinFormCSharp
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }

            public delegate void mydelegate();
            private void button1_Click(object senderEventArgs e)
            {
                Thread nonParameterThread = new Thread(new ThreadStart(button2Change));
                nonParameterThread.IsBackground = true;
                nonParameterThread.Start();

                nonParameterThread = new Thread(new ThreadStart(button1Change));
                nonParameterThread.IsBackground = true;
                nonParameterThread.Start();
            }
            public void button2Change()
            {
                for (int z = 0z < 10z++)
                {
                    string str = "";
                    str += z;
                    label2.Text = str;
                    label2.Refresh();
                    System.Threading.Thread.Sleep(300);

                }
            }

            public void button1Change()
            {
                for (int z = 0z < 10z++)
                {
                    string str = "";
                    str += z;
                    label1.Text = str;
                    label1.Refresh();
                    System.Threading.Thread.Sleep(300);

                }
            }

            private void Form1_Load(object senderEventArgs e)
            {
               
            }

        }
    }


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处
    2012年1月6日 8:01
    版主
  • 你的描述还不是很清晰,UI上的控件是要让UI控件来操控的,但是一个线程不可能同时做两件事情,所以你在主线程里面去修改label1.Text,用另外一个线程去修改label2.Text其实还是会绕到主线程去修改label2.Text的。那么也就是说不可能同时更改label1.Text和label2.Test,必定有个先后顺序,但是如果你只是想很简单地更改一下,那么直接在UI线程里面设置label1.Text和label2.Text,虽然有先后,但是肉眼肯定看不出来。
    AndersTan
    2012年1月6日 8:04
  • 首先谢谢Wei_Dong~~不过个代码运行不了~~
    2012年1月6日 9:06
  • 首先谢谢Wei_Dong~~不过个代码运行不了~~
    为什么啊?我这里可以运行的……我用VS2010,完全可以!你留下Email,给你发过去看看呢?
       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处
    2012年1月6日 9:08
    版主
  • 我用的是vs2008~~~邮箱:klvchen@126.com;谢谢

    2012年1月6日 9:36
  • 我的想法是:label1.Text 的内容变成0,接着label2.Text的内容变成0,然后label1.Text变为1,接着label2.Text变为1.。。。。。。这样轮着来~~~,不知道这样多线程能不能实现~~~多谢大家~~~

    2012年1月6日 9:40
  • 我的想法是:label1.Text 的内容变成0,接着label2.Text的内容变成0,然后label1.Text变为1,接着label2.Text变为1.。。。。。。这样轮着来~~~,不知道这样多线程能不能实现~~~多谢大家~~~

    你不是一开是说“同时变化吗”?你到底要什么啊?怎么现在又变成了“先后变化”???有图为证:

    同时变化就是我第一次回帖的那段代码,完全没有错误,至少在我这里。

    至于异步,你完全可以参考我这样的代码(你可以拷贝我下面代码,覆盖我发给你的文件)

    namespace WinFormCSharp
    {
        public partial class Form1 : Form
        {
            private static Mutex m = new Mutex(false"MyMutex");
            private static object obj = new object();
            public Form1()
            {
                InitializeComponent();
            }
     
            public delegate void mydelegate();
            private void button1_Click(object sender, EventArgs e)
            {
                Thread nonParameterThread1 = new Thread(new ThreadStart(button1Change));
                nonParameterThread1.IsBackground = true;
                nonParameterThread1.Start();
     
                Thread nonParameterThread2 = new Thread(new ThreadStart(button2Change));
                nonParameterThread2.IsBackground = true;
                nonParameterThread2.Start();
            }
            public void button2Change()
            {
                for (int z = 0; z < 10; z++)
                {
                    lock (obj)
                    {
                        m.WaitOne();
                        label2.Text = z.ToString();
                        label2.Refresh();
                        m.ReleaseMutex();
                        Thread.Sleep(500);
                    }
                }
            }
     
            public void button1Change()
            {
                for (int z = 0; z < 10; z++)
                {
                    lock (obj)
                    {
                        m.WaitOne();
                        label1.Text = z.ToString();
                        label1.Refresh();
                        m.ReleaseMutex();
                        Thread.Sleep(500);
                    }
                  
                }
            }
     
            private void Form1_Load(object sender, EventArgs e)
            {
     
            }
     
        }
    }

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处
    2012年1月7日 4:32
    版主
  • 有可能是vs2010跟vs2008的差别吧,vs2008需要用到委托函数来调用控件。

    2012年1月9日 2:39
  • 如果你确定线程只操作这些控件,最简单的方法——设置CheckForIllegalCrossThreadCalls=False(在构造函数的InitializeComponent()后边,把每一个控件的这个属性设置为False就可以了)
       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处
    • 已标记为答案 klvchen 2012年1月9日 3:37
    2012年1月9日 2:54
    版主
  • 十分感谢Wei_Dong,问题解决了!谢谢~~~
    2012年1月9日 3:37
  • 请问下:代码中声明的委托mydelegate在程序中没有用到吧,这个有用么? 我正在学多线程网络编程,想请问下委托跟多线程到底什么关系额,这里好纠结的,感激


    vortex.piggy

    2012年2月12日 8:06
  • 请问下:代码中声明的委托mydelegate在程序中没有用到吧,这个有用么? 我正在学多线程网络编程,想请问下委托跟多线程到底什么关系额,这里好纠结的,感激

    线程类Thread需要一个ThreadStart(或者是2.0新增加的一个ParameterizedThreadStart委托作为类型)。

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年2月12日 9:05
    版主
  • dear

    不建议用CheckForIllegalCrossThreadCalls=False

    这会对专案有不安定的影响,这只是治标不治本,问题根本没被解决,请参考以下

    http://www.dotblogs.com.tw/yc421206/archive/2009/02/13/7141.aspx

    http://www.dotblogs.com.tw/yc421206/category/4583.aspx


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    2012年2月13日 5:26