c# Thread.Sleep(1000); 问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c# Thread.Sleep(1000); 问题相关的知识,希望对你有一定的参考价值。

c# Thread.Sleep(1000);
运行这句时,程序就不能动了,显示“未响应”,怎么让程序既睡眠又可以使用呢
Sleep时 我只是想让界面的按钮处于可用状态

这句是让主线程睡眠1秒,当然没反映了,既睡眠又可以使用,这句话很矛盾,你要想做一件事的时候主线程还可以干别的事,那你就得新建一个子线程了 .
需要知道的是,你现在在睡眠主线程。你控件不能使用说明你睡眠的是ui线程,你可以用后台线程来处理数据,ui在前台干别的事
参考技术A 这句的意思就是让线程休眠1秒,一秒后该线程应该是等待醒来状态,如果此时他得到cpu并且他申请的资源可用那么他将自己继续执行。
你说的情况是不是这个线程需要用到的资源被别的线程锁了
参考技术B 你的线程开了几个,这个是睡眠的一秒的,如果想使用,开另一个线程做你想做的事 参考技术C 应该是执行啦,在你调试的过程中就执行啦,因为你设的时间才一秒钟,可以设长点效果可能明显些,如thread.sleep(3000); 参考技术D 这就矛盾了吧?既然睡眠了,怎么可以做其他事情?

C# 中的 Thread.Sleep(1) 有啥影响?

【中文标题】C# 中的 Thread.Sleep(1) 有啥影响?【英文标题】:What is the impact of Thread.Sleep(1) in C#?C# 中的 Thread.Sleep(1) 有什么影响? 【发布时间】:2009-02-03 17:59:29 【问题描述】:

在 windows 窗体应用程序中调用Thread.Sleep(1) 有什么影响,如下代码所示:

public Constructor()

    Thread thread = new Thread(Task);
    thread.IsBackground = true;
    thread.Start();


private void Task()

    while (true)
    
        // do something
        Thread.Sleep(1);
    

这个线程会占用所有可用的 CPU 吗?

我可以使用哪些分析技术来测量此线程的 CPU 使用率(任务管理器除外)?

【问题讨论】:

到目前为止的所有答案都表明效果可以忽略不计,但你能否澄清一下你试图用这个来完成什么? 我只是想看看我的 GUI 应用程序是否因为短暂的 1 毫秒延迟而将所有时间都花在了这个线程上。 【参考方案1】:

如上所述,您的循环不会占用 CPU。

但请注意:Windows 不是实时操作系统,因此您将不会每秒从 Thread.Sleep 获得 1000 次唤醒( 1)。如果您没有使用timeBeginPeriod 设置您的最小分辨率,您将每 15 毫秒唤醒一次。即使您将最小分辨率设置为 1 毫秒,您仍然只会每 3-4 毫秒唤醒一次。

为了获得毫秒级计时器粒度,您必须使用 Win32 多媒体计时器 (C# wrapper)。

【讨论】:

你能举一个在C#中设置timeBeginPeriod的例子吗? pinvoke.net/default.aspx/winmm.timeBeginPeriod 根据 MSDN 文档,timeBeginPeriod 应该与 timeEndPeriod 调用相匹配。另请注意“此功能会影响全局 Windows 设置”。并且会影响系统性能。【参考方案2】:

不,它不会占用 CPU,它只会暂停你的线程至少那么长时间。当您的线程暂停时,操作系统可以调度另一个不相关的线程来使用处理器。

【讨论】:

不过,这会不必要地占用大量 CPU 时间。 @Joel 如何/为什么会花费更多时间而不是一段时间(真的) i++; 还是在 CPU 使用率方面基本相同? 在现代 CPU 上,与使用 i++ 相比,1ms 的睡眠是永恒的。 @Joel 相对于 10 功能计算器的总可用 CPU 时间,是的,这将占用“很多”CPU 时间。相对于过去十年制造的任何机器的可用 CPU 时间,它将使用大约零 CPU 时间。【参考方案3】:

Thread.Sleep(1) 如上所述不会占用 CPU。

当线程休眠(或多或少)时会发生以下情况:

Thread.Sleep 被转换为系统调用,进而触发陷阱(允许操作系统控制的中断) 操作系统检测到睡眠调用并将您的线程标记为阻塞。 操作系统在内部保留了需要唤醒的线程列表以及唤醒时间。 由于线程不再使用 CPU 操作系统... 如果父进程没有用完其所有时间片,操作系统将安排该进程的另一个线程执行。 否则另一个进程(或空闲进程)将开始执行。 时间到了,你的线程会被重新调度执行,但这并不意味着它会自动开始执行。

最后一点,我不完全知道您在做什么,但您似乎正在尝试扮演调度程序的角色,也就是说,睡觉以为 CPU 提供时间来做其他事情。 .

在少数情况下(确实很少)可能没问题,但大多数情况下你应该让调度程序完成它的工作,它可能比你知道的更多,并且可以让工作比你能做的更好

【讨论】:

【参考方案4】:

应避免较短的睡眠时间,因为放弃其时间片的线程在重新发出信号时会获得优先级提升,这可能导致高上下文切换。在多线程/服务器应用程序中,这可能会导致抖动效应,因为线程正在争夺 CPU 时间。相反,请依赖异步函数和同步对象,例如临界区或互斥体/信号量。

【讨论】:

【参考方案5】:

正如 Bob Nadler 提到的,Thread.Sleep(1) 不保证 1 毫秒的睡眠时间。

这是一个使用 Win32 多媒体计时器强制休眠 1 毫秒的示例。

    [DllImport("winmm.dll")]
    internal static extern uint timeBeginPeriod(uint period);
    [DllImport("winmm.dll")]
    internal static extern uint timeEndPeriod(uint period);

    timeBeginPeriod(1);
    while(true)
    
        Thread.Sleep(1); // will sleep 1ms every time
    
    timeEndPeriod(1);

在 C# GUI 应用程序中对此进行测试,我发现该应用程序使用了大约 50% 的 CPU。

有关此主题的更多讨论,请参阅以下论坛主题:

http://www.dotnet247.com/247reference/msgs/57/289291.aspx

【讨论】:

【参考方案6】:

这是一个旧线程,在我的很多搜索中都会出现,但 Win7 有一个新的调度程序,并且其行为似乎与上述不同。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication2

    class Program
    
        static void Main(string[] args)
        
            DateTime dtEnd = DateTime.Now.AddSeconds(1.0);
            int i = 0;
            while (DateTime.Now < dtEnd)
            
                i++;
                Thread.Sleep(1);
            

            Console.WriteLine(i.ToString());

            i = 0;
            long lStart = DateTime.Now.Ticks;
            while (i++ < 1000)
                Thread.Sleep(1);

            long lTmp = (DateTime.Now.Ticks - lStart) / 10000;

            Console.WriteLine(lTmp.ToString());

            Console.Read();
        
    

使用上面的代码,我的第一个结果是 946。所以在使用 1ms 睡眠的 1 秒时间跨度内,我得到了 946 次唤醒。这非常接近 1 毫秒。

第二部分询问以 1ms 的时间完成 1000 个睡眠事件需要多长时间。我得到了 1034 毫秒。同样,将近 1 毫秒。

这是在 1.8ghz core2duo + Win7 上使用 .Net 4.0

编辑:记住,sleep(x) 并不意味着在这个时候醒来,它意味着不早于这个时候叫醒我。不能保证。不过,您可以提高线程的优先级,并且 Windows 应该在较低优先级的线程之前安排您的线程。

【讨论】:

关于 Win 7 调度程序的评论。我运行了 Bengie 的示例“命名空间 ConsoleApplication2”帖子,它报告了 65 和 15600,表示大约 15 毫秒的步骤。这是一个运行 .NET 3.5、Win 7 的双 3.33Mhx。奇怪的是,昨天我的日志中有一些代码显示 sleep(1) 更接近 1ms,就像他的帖子声称的那样。我的结论是我的机器上有一些设置或配置发生了变化,但我无法确定。在带有或不带有调试器的调试或发布模式下,答案相同。我没有使用开始/结束时间段。 ma上的负载很小【参考方案7】:

不,它不会占用所有可用的 CPU,因为当另一个线程有工作要做时,操作系统的调度程序会关闭一个睡眠线程。

【讨论】:

【参考方案8】:

不,不会。你几乎看不到它。大约每秒不到 1000 次,这个线程会在再次入睡之前醒来并且几乎什么都不做。

编辑:

我必须检查一下。在 Java 1.5 上运行,此测试

@Test
public void testSpeed() throws InterruptedException 
    long currentTime = System.currentTimeMillis();
    int i = 0;
        while (i < 1000)
        
            Thread.sleep(1);
            i++;
        
    System.out.println("Executed in " + (System.currentTimeMillis() - currentTime));

在我的 3ghz 机器上以每秒大约 500 次睡眠的速度运行。我想C#应该差不多。我假设有人会为这个非常重要的现实世界基准测试报告 C# 数字。顺便说一句,没有可观察到的 CPU 使用率。

【讨论】:

我怀疑它是否会经常发生:睡眠的参数是最短时间,而上下文切换需要很长时间才能得到很多。 在现代多核系统上,1ms 是一个非常长的时间。我想知道这个循环实际上是如何运行的?【参考方案9】:

一个线程一次最多只能占用一个(逻辑)CPU。并且 1 毫秒的睡眠不会占用太多时间。不要出汗。

【讨论】:

【参考方案10】:

也看看这个:msdn forum

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace Test

    public static class Program
    
        public static void Main(string[] args)
        
            Stopwatch sw = new Stopwatch();

            for (int i = 0; i < 10; ++i)
            
                sw.Reset();
                sw.Start();
                Thread.Sleep(50);
                sw.Stop();

                Console.WriteLine("(default) Slept for " + sw.ElapsedMilliseconds);

                TimeBeginPeriod(1);
                sw.Reset();
                sw.Start();
                Thread.Sleep(50);
                sw.Stop();
                TimeEndPeriod(1);

                Console.WriteLine("(highres) Slept for " + sw.ElapsedMilliseconds + "\n");
            
        

        [DllImport("winmm.dll", EntryPoint="timeBeginPeriod", SetLastError=true)]
        private static extern uint TimeBeginPeriod(uint uMilliseconds);

        [DllImport("winmm.dll", EntryPoint="timeEndPeriod", SetLastError=true)]
        private static extern uint TimeEndPeriod(uint uMilliseconds);
    

【讨论】:

以上是关于c# Thread.Sleep(1000); 问题的主要内容,如果未能解决你的问题,请参考以下文章

[C#] 匿名方法的方便和安全

java中Thread.sleep(1000)问题

C# 中的 Thread.Sleep(1) 有啥影响?

在c#中使用线程延迟执行方法

java中的thread.sleep(1000) 用法

C#中的Task.Delay()和Thread.Sleep()区别