新手求解线程延时问题

michaeliao 2019-02-28 11:10:27
我想测试子线程和主线程之间的延时问题,简单的写了一个程序。界面如下:




private void button1_Click(object sender, EventArgs e)
{
ThreadStart ths1 = new ThreadStart(ShowThread1);
ThreadStart ths2 = new ThreadStart(ShowThread2);

Thread th1 = new Thread(ths1);
Thread th2 = new Thread(ths2);

th1.Start();
th2.Start();

for (int i = 0; i < 1000; i++)
{
System.Threading.Thread.Sleep(300);
if (textBox1.InvokeRequired)
{
this.Invoke(new EventHandler(delegate
{
textBox1.Text = i.ToString();
}));
}
else
{
textBox1.Text = i.ToString();
textBox1.Refresh();
}
Application.DoEvents();
}
}

private void ShowThread1()
{
int i = 0;

for (i = 0; i < 1000; i++)
{
if (textBox2.InvokeRequired)
{
this.Invoke(new EventHandler(delegate
{
textBox2.Text = i.ToString();
textBox2.Refresh();
}));
}
else
{
textBox2.Text = i.ToString();
textBox2.Refresh();
}
System.Threading.Thread.Sleep(100);
}
}

private void ShowThread2()
{
int i = 0;

for (i = 0; i < 1000; i++)
{
if (textBox3.InvokeRequired)
{
this.Invoke(new EventHandler(delegate
{
textBox3.Text = i.ToString();
textBox3.Refresh();
}));
}
else
{
textBox3.Text = i.ToString();
textBox3.Refresh();
}
System.Threading.Thread.Sleep(200);
}
}


我的理解是每个线程延时不一样,界面上更新的数字应该也不一样,但是最终运行结果是3个Textbox是同时更新,而且更新的数字也是一样的,有没有高手能够给我解释一下什么原因吗?我该如何实现预想的效果(也就是TextBox1隔300ms更新一次,TextBox2隔100ms更新一次,TextBox3隔200ms更新一次)呢?
...全文
1027 1 收藏 29
写回复
29 条回复
菠萝印象威 2019年03月04日
sleep阻塞,你会发现sleep过程中不能操作,否则程序卡死
回复 点赞
wid999 2019年03月03日
引用 25 楼 welcome520 的回复:
[quote=引用 21 楼 sp1234_maJia的回复:]在很久以前,我们使用 vb(4、5、6)来写游戏软件,游戏中有大量的精灵都需要定时按帧操作,但是 vb 只能按照单线程的思想来编程,于是我们就清楚地知道了如何合理地编程高度并发、灵活界面、流畅交互的程序。注意是在单线程的系统中开发高度并发——分时的——游戏程序。实际上早期的很多游戏也都是如此。其它的一些强调并发操作的 vb 程序,例如大型的需要支持几百台收银机的百货零售业的服务器程序(用vb开发的,跑在 IBM 小型机上的服务器程序)也是如此。

可能因为这一点,所以我会更多强调,不要满脑子只有什么“线程”概念,要学习更本质的设计思路。那样你不管用不用“线程”,起码你都在轻松地开发高度并发的算法流程。而不会以为只要知道“多核、Thread”概念就能高并发。

请问,单线程中怎么开发高度并发程序[/quote]

说的应该是“中断”这个概念。
回复 点赞
xialonghua 2019年03月02日
线程一切都是不确定的
回复 点赞
朱振華 2019年03月02日
线程一切都是不确定的。。。。。。。。。。。。。。。。。。。。。
回复 点赞
desperaso 2019年03月01日
你的代码的效果

private void button1_Click(object sender, EventArgs e)
{
ThreadStart ths0 = new ThreadStart(ShowThread0);
ThreadStart ths1 = new ThreadStart(ShowThread1);
ThreadStart ths2 = new ThreadStart(ShowThread2);

Thread th0 = new Thread(ths0);
Thread th1 = new Thread(ths1);
Thread th2 = new Thread(ths2);

th0.Start();
th1.Start();
th2.Start();
}

private void ShowThread0()
{
int i = 0;
for ( i = 0; i < 1000; i++)
{
System.Threading.Thread.Sleep(300);

if (textBox1.InvokeRequired)
{
this.Invoke(new EventHandler(delegate
{
textBox1.Text = i.ToString();
}));
}
else
{
textBox1.Text = i.ToString();
textBox1.Refresh();
}
}
}

private void ShowThread1()
{
int i = 0;

for (i = 0; i < 1000; i++)
{
if (textBox2.InvokeRequired)
{
this.Invoke(new EventHandler(delegate
{
textBox2.Text = i.ToString();
textBox2.Refresh();
}));
}
else
{
textBox2.Text = i.ToString();
textBox2.Refresh();
}
System.Threading.Thread.Sleep(100);
}
}

private void ShowThread2()
{
int i = 0;

for (i = 0; i < 1000; i++)
{
if (textBox3.InvokeRequired)
{
this.Invoke(new EventHandler(delegate
{
textBox3.Text = i.ToString();
textBox3.Refresh();
}));
}
else
{
textBox3.Text = i.ToString();
textBox3.Refresh();
}
System.Threading.Thread.Sleep(200);
}
}
回复 点赞
wwwspider001 2019年03月01日
再仔细看看题主的题目吧,呵呵 明明只是想搞明白线程间的关系,却一直在高谈阔论要用异步,异步能高并发,,,, 异步这东西也不是什么新概念,发展到现在基本上是语言都有支持了,完全不需要更多强调了,呵呵 另外,IBM小型机,vb开发,支持几百台收银机的大型服务器程序,不知道卖IBM小型机的是要骂娘呢,还是该偷着乐呢,而且应该也是十几二十年前的事情了吧,,,懂得自然懂,不懂的多说无益。 今天闲的有点蛋疼,匿了先。。。
回复 点赞
以专业开发人员为伍 2019年03月01日
满脑子只有一个“当前的语句”的所谓保证延时的做法,其实是坑爹的。同时在 windows 系统下运行的进程、以及进程中的线程,累计起来何止上千?你随便一个线程就要阻塞、甚至要去胡乱修改操作系统参数来霸占时间片?这只会用看似高大上的语句,其实是做了刚学编程时才喜欢的那种“练习题”。你真正需要学习地是大系统的文明的异步高并发程序设计原则,而不要学那些如何独占、霸占时间片的个别语句。
回复 点赞
以专业开发人员为伍 2019年03月01日
你在 UI 主线程中使用 Sleep、for 循环来卡死了主线程,这会造成许多问题。 即使是在(UI主线程启动的)子线程中使用 Sleep 阻塞,其实也是十几、二十几年前的早期做法。在一个比较灵活的交互程序中,需要定时的地方又何止成百上千?!每一个线程都要占用至少1M栈空间,都需要消耗操作系统的抢占和调度的时空。 你要设计大量的定时操作(例如游戏里每一个精灵都要有按帧动画),或者异步操作,如果你只会 Sleep 概念,那么还不如什么“线程”概念都没学。 因为真正的高性能的分时并发操作,不能胡乱写什么 Sleep 代码。那么也就用不着什么 Refresh 以及其它语句。
回复 点赞
desperaso 2019年03月01日
补充下Sleep精度
http://blog.sina.com.cn/s/blog_a459dcf50102uy1g.html
回复 点赞
aRwanG 2019年03月01日
@以专业开发人员为伍 太强大了
回复 点赞
desperaso 2019年03月01日
sleep控制

[DllImport("winmm.dll", EntryPoint = "timeBeginPeriod")]
public static extern uint _BeginPeriod(uint uMilliseconds);
[DllImport("winmm.dll", EntryPoint = "timeEndPeriod")]
public static extern uint _EndPeriod(uint uMilliseconds);

private void chg_Half(object half)
{
while (true)
{
...............
_BeginPeriod(5);
Thread.sleep(5);
_EndPeriod(5);
}
break;
}
}
回复 点赞
以专业开发人员为伍 2019年03月01日
真正的异步定时操作,是不会在所谓的 for 循环时去“卡死、独占当前线程的"。 所以所谓“线程”概念让一些人疯狂,实际上只知道滥用线程害人。关键就是滥用 Sleep 害人!
回复 点赞
以专业开发人员为伍 2019年03月01日
引用 4 楼 michaeliao 的回复:
我试了一下,发现主线程的延时不能大于子线程的延时,大于子线程的延时的话,就会出现上面说的问题。 如果主线程的延时小于子线程的延时,就会按照设定的运行。刷新也是没有问题的
Sleep 是编程大忌,它是阻塞的语法(而不是异步线程的),由于阻塞就会让人诡异地去用更多错误的做法来开发。
回复 点赞
以专业开发人员为伍 2019年03月01日
private void button1_Click(object sender, EventArgs e)
{
    Task.Run(async () =>
    {
        for (var i = 0; i < 1000; i++)
        {
            this.BeginInvoke((Action)(() =>
            {
                this.label1.Text = i.ToString();
            }));
            await Task.Delay(300);
        }
    });
    Task.Run(async () =>
    {
        for (var i = 0; i < 1000; i++)
        {
            this.BeginInvoke((Action)(() =>
            {
                this.label2.Text = i.ToString();
            }));
            await Task.Delay(100);
        }
    });
    Task.Run(async () =>
    {
        for (var i = 0; i < 1000; i++)
        {
            this.BeginInvoke((Action)(() =>
            {
                this.label3.Text = i.ToString();
            }));
            await Task.Delay(200);
        }
    });
}
回复 点赞
北京.NET 2019年03月01日


把这个也单独也写个线程就好了
回复 点赞
welcome520 2019年03月01日
引用 21 楼 sp1234_maJia的回复:
在很久以前,我们使用 vb(4、5、6)来写游戏软件,游戏中有大量的精灵都需要定时按帧操作,但是 vb 只能按照单线程的思想来编程,于是我们就清楚地知道了如何合理地编程高度并发、灵活界面、流畅交互的程序。注意是在单线程的系统中开发高度并发——分时的——游戏程序。实际上早期的很多游戏也都是如此。其它的一些强调并发操作的 vb 程序,例如大型的需要支持几百台收银机的百货零售业的服务器程序(用vb开发的,跑在 IBM 小型机上的服务器程序)也是如此。 可能因为这一点,所以我会更多强调,不要满脑子只有什么“线程”概念,要学习更本质的设计思路。那样你不管用不用“线程”,起码你都在轻松地开发高度并发的算法流程。而不会以为只要知道“多核、Thread”概念就能高并发。
请问,单线程中怎么开发高度并发程序
回复 点赞
michaeliao 2019年03月01日
有人能解释一下这个是什么原因吗?难道Sleep在主线程延时的时候,所有子线程也休眠了?
回复 点赞
michaeliao 2019年03月01日
我试了一下,发现主线程的延时不能大于子线程的延时,大于子线程的延时的话,就会出现上面说的问题。
如果主线程的延时小于子线程的延时,就会按照设定的运行。刷新也是没有问题的
回复 点赞
左耳边的期盼 2019年03月01日
学习中,帮你顶顶
回复 点赞
exception92 2019年03月01日
查询一下Application.DoEvents的作用即可。
回复 点赞
发动态
发帖子
C#
创建于2007-09-28

8.4w+

社区成员

64.0w+

社区内容

.NET技术 C#
社区公告
暂无公告