多线程中两个线程无法同步运行

agjaisdjfo 2015-11-28 10:25:10
我的想法是创建一个新线程,然后主线程在后台输出“j=~",然后新线程在进度跳上没0.5秒增加1进度。但是实际中只有主线程在后台输出,而新建的线程无法控制进度条。新手对这方面不明白,看了一些资料也没有找到答案,还请各位不惜赐教,十分感谢!

private delegate void myDelegate1();

private void SetProgressBar1()
{
progressBar1.Value = 0;

Console.Out.WriteLine("thread start");
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(500);
progressBar1.Value = i + 1;
}
Console.Out.WriteLine("thread is over");
}

private void TRun1()
{
//判断控件是否在本线程内
if (!this.progressBar1.InvokeRequired)
{
MessageBox.Show("TRun1同一线程内");
Thread.Sleep(2000);
}
else
{
myDelegate1 md1 = new myDelegate1(SetProgressBar1);
MessageBox.Show("TRun1不是同一个线程");
Invoke(md1);
}
}

private void button1_Click(object sender, EventArgs e)
{
// RunWithInvoke();
Thread thread = new Thread(TRun1);
thread.Start();
for (int j = 0; j < 100; j++)
{
System.Threading.Thread.Sleep(500);
Console.Out.WriteLine("j=" + j.ToString());
}
}
...全文
319 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
绿豆丫 2016-02-27
  • 打赏
  • 举报
回复
引用 6 楼 xarrows 的回复:

        private void button6_Click(object sender, EventArgs e)
        {
            this.progressBar2.Value = 0;
            this.progressBar2.Minimum = 0;
            this.progressBar2.Maximum = 100000;//为了看到效果

            Thread th = new Thread(ChangeProgressMethod);
            th.IsBackground = true;
            th.Start(this.progressBar2.Value);
            
        }
        private delegate void ChangeProgressDelegate(object data);
        private void ChangeProgressMethod(object data)
        {
            while (true)
            {
                if (this.progressBar2.Value >= this.progressBar2.Maximum) break;

                ChangeProgressDelegate cp = new ChangeProgressDelegate(ChangeProgressMethod);

                if (this.progressBar2.InvokeRequired)
                {
                    this.progressBar2.Invoke(cp, data);
                    Console.Out.WriteLine("Invoke");
                }
                else
                {

                    Console.Out.WriteLine(this.progressBar2.Value);//这里如果注释掉,UI不会卡住,因为很快执行完成
                    //会不会是这个console的原因,它使用了另UI的线程,才导致UI界面卡住了,这里要怎样才能找到问题的根源。
                    //另外如果加上Application.Doevents()就不会卡住了,但貌似跟直接在按钮里面不开新线程运行没什么区别。
                    data = Convert.ToInt32(data) + 1;
                    this.progressBar2.Value = Convert.ToInt32(data);
                }
                
            }
        }
这里的Console.Out.WriteLine跟UI应该是同一个线程,所以会卡住。
  • 打赏
  • 举报
回复
这里的关键点很简单,这里的主要的计算(用Sleep来代替模拟)是在子线程中执行的,而仅仅在必须要显示结果时才注册到主线程去执行。 而你的 SetProgressBar1 方法,整个注册到主线程去执行了,还怎么能在子线程玩耍?
  • 打赏
  • 举报
回复
要想测试一下子线程进度的处理,可以这样写
private void Form1_Load(object sender, EventArgs e)
{
    ThreadPool.QueueUserWorkItem(h =>
    {
        var rnd = new Random();
        for(var i=0; i<100; ++i)
        {
            Thread.Sleep(rnd.Next(500));
            this.progressBar1.BeginInvoke((Action)delegate
            {
                this.progressBar1.Value = i;
            });
        }
    });
}
当然,你把 BeginInvoke 写成 Invoke 也可以(我是从来不写 Invoke),在此只是一点点体验上的差别(后者变慢)。
  • 打赏
  • 举报
回复
引用 5 楼 u013421223 的回复:
这代码写的有问题。

private void SetProgressBar1()
        {
            progressBar1.Value = 0;
 
            Console.Out.WriteLine("thread start");
            for (int i = 0; i < 100; i++)
            {
                System.Threading.Thread.Sleep(500);
                progressBar1.Value = i + 1;
            }
            Console.Out.WriteLine("thread is over");
        }
Invoke将这代码放到主线程里面执行,这这段至少50s执行完。 你应该开线程后,在线程里面循环,隔一段时间去修改一次。你不能连续让主线程干那么久
是这样的。 你的 SetProgressBar1 明明在主线程中执行,你是怎么误以为是在子线程执行的呢? 另外,你的 SetProgressBar1 既然在主线程执行,你的 for 循环执行完(i 变量值为100)之后才把主线程控制交还给 windows 的 UI 处理,那么自然你就一下子只能看到循环之后的结果了,看不到过程了。
七步777 2016-02-26
  • 打赏
  • 举报
回复
这代码写的有问题。

private void SetProgressBar1()
        {
            progressBar1.Value = 0;
 
            Console.Out.WriteLine("thread start");
            for (int i = 0; i < 100; i++)
            {
                System.Threading.Thread.Sleep(500);
                progressBar1.Value = i + 1;
            }
            Console.Out.WriteLine("thread is over");
        }
Invoke将这代码放到主线程里面执行,这这段至少50s执行完。 你应该开线程后,在线程里面循环,隔一段时间去修改一次。你不能连续让主线程干那么久
绿豆丫 2016-02-26
  • 打赏
  • 举报
回复

        private void button6_Click(object sender, EventArgs e)
        {
            this.progressBar2.Value = 0;
            this.progressBar2.Minimum = 0;
            this.progressBar2.Maximum = 100000;//为了看到效果

            Thread th = new Thread(ChangeProgressMethod);
            th.IsBackground = true;
            th.Start(this.progressBar2.Value);
            
        }
        private delegate void ChangeProgressDelegate(object data);
        private void ChangeProgressMethod(object data)
        {
            while (true)
            {
                if (this.progressBar2.Value >= this.progressBar2.Maximum) break;

                ChangeProgressDelegate cp = new ChangeProgressDelegate(ChangeProgressMethod);

                if (this.progressBar2.InvokeRequired)
                {
                    this.progressBar2.Invoke(cp, data);
                    Console.Out.WriteLine("Invoke");
                }
                else
                {

                    Console.Out.WriteLine(this.progressBar2.Value);//这里如果注释掉,UI不会卡住,因为很快执行完成
                    //会不会是这个console的原因,它使用了另UI的线程,才导致UI界面卡住了,这里要怎样才能找到问题的根源。
                    //另外如果加上Application.Doevents()就不会卡住了,但貌似跟直接在按钮里面不开新线程运行没什么区别。
                    data = Convert.ToInt32(data) + 1;
                    this.progressBar2.Value = Convert.ToInt32(data);
                }
                
            }
        }
苏州吴彦祖 2016-02-25
  • 打赏
  • 举报
回复
子线程就运行 1次 你没写while 你应该在主线程启动时 也启动 子线程
Poopaye 2015-11-30
  • 打赏
  • 举报
回复
引用 2 楼 zhuce_ly 的回复:
[quote=引用 1 楼 shingoscar 的回复:] 因为MessageBox.Show会把线程阻塞掉
不是这个原因,我把MessageBox.Show注释掉也是一样的问题[/quote] 还有,因为Invoke里的md1也要通过UI线程来运行,但是UI线程被button1_Click里的Thread.Sleep给阻塞了 所以现在应该先等那100条显示完了才会再进到SetProgressBar1里
agjaisdjfo 2015-11-30
  • 打赏
  • 举报
回复
引用 1 楼 shingoscar 的回复:
因为MessageBox.Show会把线程阻塞掉
不是这个原因,我把MessageBox.Show注释掉也是一样的问题
Poopaye 2015-11-28
  • 打赏
  • 举报
回复
因为MessageBox.Show会把线程阻塞掉

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧