下面是一个控制台程序,它想要批量启动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中开始和结束。
Thread.Sleep会影响其他线程吗?有没有办法让你有一个纯粹的空闲时间呢?
/-----------------------------edit
同样的问题也发生在:
static void Main(string[] args)
{
System.Threading.Tasks.Parallel.For(0, 10, (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, 10, (index) =>
{
Console.Write("start {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 ");
}发布于 2011-06-01 11:04:28
这是设计好的。您将看到线程池管理器试图将有限数量的线程保持在正在执行状态。重要的是要确保您的程序运行的线程数不会超过计算机的cpu核心数。这是低效的,当Windows被迫开始在活动线程之间交换内核时,完成的工作会更少。线程池管理器不够智能,不知道线程正在休眠,实际上没有执行任何工作。
在双核机器上,您将看到前两个线程立即启动。然后,当线程管理器注意到活动线程没有任何进展并且可能被阻塞时,允许额外的线程以一秒的间隔逐个运行。线程被释放并执行Console.Write()调用的顺序是不确定的。
当然,这是一个人工测试,真正的线程不会休眠。如果你有长时间阻塞的线程,例如等待I/O请求完成,那么使用线程池线程(任务)不是最好的解决方案。
发布于 2011-06-01 11:16:38
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,它将以与Parallel.For完全相同的方式运行。
发布于 2011-06-01 11:12:01
我稍微更新了代码,以便在写入控制台时显示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} ", index, Thread.CurrentThread.ManagedThreadId.ToString(), 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 PMhttps://stackoverflow.com/questions/6195672
复制相似问题