微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Thread.Sleep是否会阻碍其他线程?

如何解决Thread.Sleep是否会阻碍其他线程?

| 这是一个控制台程序,要批量启动10个线程,等待5秒钟,然后批量停止。
static void Main(string[] args)
{
    System.Threading.Tasks.Parallel.For(0,10,(index) =>
    {
        Action<int> act = (i) =>
        {
            Console.Write(\"start {0} \",i);
            Thread.Sleep(5000);
        };

        act.BeginInvoke(index,OnTaskComplete,index);
    });

    Console.ReadKey();
}

static void OnTaskComplete(IAsyncResult res)
{
    Console.Write(\"finish {0} \",res.AsyncState);
}
但是结果不是我所期望的,10个线程缓慢地(大约1秒间隔)一个一个地启动,甚至在某些“启动”之前就出现了一些“完成”。 当注释掉Thread.Sleep时,所有线程都在Flash中开始和结束。 ѭ1影响其他线程吗?无论如何,有没有一个纯粹的空闲时间? / - - - - - - - - - - - - - - -编辑 - - - - - - - - - - ---------- 同样的问题也发生在:
static void Main(string[] args)
{
    System.Threading.Tasks.Parallel.For(0,(index) =>
    {
        Console.Write(\"start {0} \",index);
        Thread.Sleep(5000);
        Console.Write(\"fnish {0} \",index);
    });

    Console.ReadKey();
}
- - - - - - - - - - - 编辑 - - - - - - - - - - - - 终于我找到了一种替代thread.sleep的好方法
static void Main(string[] args)
{
    System.Threading.Tasks.Parallel.For(0,index);

        var t1 = new System.Threading.Timer(new TimerCallback(MyTimerCallback),index,5000,0); 
    });

    Console.ReadKey();
}

static void MyTimerCallback(object o)
{
    Console.Write(\"Timer callbacked \");
}
    

解决方法

        这是设计使然。您会看到线程池管理器试图将有限数量的线程保持在执行状态。确保您的程序运行的线程数不超过计算机具有cpu内核的线程,这一点很重要。当Windows被迫开始在活动线程之间交换内核时,效率低下,工作量减少。线程池管理器不够聪明,无法知道线程正在休眠并且实际上没有执行任何工作。 在双核计算机上,您会立即看到前两个线程。然后,当线程管理器注意到活动线程没有取得任何进展并且可能被阻塞时,允许其他线程以一秒钟的间隔逐个运行。释放线程并执行Console.Write()调用的顺序不确定。 当然,这是一个人工测试,真实线程不会休眠。如果您有长时间阻塞的线程,例如,等待I / O请求完成,则使用线程池线程(任务)不是最佳解决方案。     ,        
TaskCreationOptions.LongRunning
将“删除” ThreadPool限制。 我不知道为
Parallel.For
指定
TaskCreationOptions.LongRunning
的简单方法。 但是,您可以使用Task类实现相同的效果:
Action<int> action = i =>
    {
        Console.Write(\"start {0} \",i);
        Thread.Sleep(5000);
        Console.Write(\"finish {0} \",i);
    };

var tasks = Enumerable.Range(0,100)
    .Select(arg => Task.Factory.StartNew(() => action(arg),TaskCreationOptions.LongRunning))
    .ToArray();

Task.WaitAll(tasks);
如果没有
TaskCreationOptions.LongRunning
,它将以与as6ѭ完全相同的方式运行。     ,        我稍作更新了代码,以在写入控制台时显示ThreadID:
Console.WriteLine(\"start index:{0} thread id:{1} Time:{2} \",index,Thread.CurrentThread.ManagedThreadId.ToString(),DateTime.Now.ToLongTimeString());
Thread.Sleep(5000);
ConsoleWriteLine(\"finish index:{0} thread id:{1} Time:{2} \",DateTime.Now.ToLongTimeString());
我的机器是双核的,这是我得到的输出。这应该使您对正在发生的事情有所了解。请记住,循环可能并不总是按顺序运行,即0到9是并行的,它会抢占数组的一部分并通过lambda运行每一项。 输出:
start  index:1 thread id:11 Time:11:07:17 PM
start  index:0 thread id:9  Time:11:07:17 PM
start  index:5 thread id:10 Time:11:07:17 PM
start  index:6 thread id:12 Time:11:07:18 PM
start  index:2 thread id:13 Time:11:07:19 PM
start  index:7 thread id:14 Time:11:07:20 PM
start  index:3 thread id:15 Time:11:07:21 PM
start  index:8 thread id:16 Time:11:07:22 PM
finish index:0 thread id:9  Time:11:07:22 PM
start  index:4 thread id:9  Time:11:07:22 PM
finish index:1 thread id:11 Time:11:07:22 PM
start  index:9 thread id:11 Time:11:07:22 PM
finish index:5 thread id:10 Time:11:07:22 PM
finish index:6 thread id:12 Time:11:07:23 PM
finish index:2 thread id:13 Time:11:07:24 PM
finish index:7 thread id:14 Time:11:07:25 PM
finish index:3 thread id:15 Time:11:07:26 PM
finish index:8 thread id:16 Time:11:07:27 PM
finish index:4 thread id:9  Time:11:07:27 PM
finish index:9 thread id:11 Time:11:07:27 PM
    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。