StartNew(Action<object> action,object state,CancellationToken cancellationToken,TaskCreationOptions creationOptions,TaskScheduler scheduler);
当工作代码实际开始执行时.
我创建了一个测试来显示:
public static class TestTaskFactory { private class TaskInfo { public int Number; } private static int NUM_TASKS = 5; private static int NumFinished = 0; public static void Run() { for (int n = 1; n <= NUM_TASKS; n++) { Log("Starting task #" + n + " ..."); var task_info = new TaskInfo { Number = n }; var task = Task.Factory.StartNew(Worker,task_info,CancellationToken.None,TaskCreationOptions.None,TaskScheduler.Default); Thread.Sleep(0); } Log("Waiting for tasks to finish ..."); while (NumFinished < NUM_TASKS) { Thread.Sleep(1); } Log("All done"); } private static void Worker(object state) { var task_info = (TaskInfo)state; Log("Task #" + task_info.Number + " running"); // Do something Thread.Sleep(2000); // Done ++NumFinished; } private static void Log(string msg) { Console.WriteLine(DateTime.Now.ToString("HH.mm.ss.fff") + ": Thread " + Thread.CurrentThread.ManagedThreadId + ": " + msg); } }
Mac下Mono下的输出:
16.57.31.420: Thread 1: Starting task #1 ... 16.57.31.508: Thread 1: Starting task #2 ... 16.57.31.508: Thread 1: Starting task #3 ... 16.57.31.508: Thread 1: Starting task #4 ... 16.57.31.508: Thread 1: Starting task #5 ... 16.57.31.508: Thread 1: Waiting for tasks to finish ... 16.57.31.510: Thread 5: Task #1 running 16.57.32.009: Thread 6: Task #2 running <-- Approx 500 msec later 16.57.32.511: Thread 7: Task #3 running <-- Approx 500 msec later 16.57.33.012: Thread 8: Task #4 running <-- Approx 500 msec later 16.57.33.513: Thread 9: Task #5 running <-- Approx 500 msec later 16.57.35.515: Thread 1: All done
就好像Mono想要在产生新线程之前等待500毫秒来重用现有线程.如果我将工作时间减少到500毫秒以下,则延迟会减少.例如,将worker Thread.Sleep(2000)更改为Thread.Sleep(50):
... 17.13.20.262: Thread 5: Task #1 running 17.13.20.314: Thread 5: Task #2 running <-- approx 50 msec later 17.13.20.365: Thread 5: Task #3 running <-- approx 50 msec later 17.13.20.416: Thread 5: Task #4 running <-- approx 50 msec later 17.13.20.466: Thread 5: Task #5 running <-- approx 50 msec later
但是在MS Framework 4.0下,工作代码开始之前没有大的延迟:
... 17.05.42.238: Thread 9: Waiting for tasks to finish ... 17.05.42.256: Thread 11: Task #1 running 17.05.42.256: Thread 12: Task #3 running <-- little delay 17.05.42.256: Thread 13: Task #4 running <-- little delay 17.05.42.257: Thread 10: Task #2 running <-- little delay 17.05.43.264: Thread 14: Task #5 running <-- little delay
在我提交关于Mono的错误报告之前,我想要理智地检查我是否错过了我需要在Mono上进行的一些调整或使用Task.Factory错误.我实际上在我的真实应用程序中使用了最大并发调度程序.
所以我的问题是:这是Mono / MonoTouch中的一个错误吗?
更新:我已经从使用Mono *下的ThreadPool切换到Ami Bar的智能线程池(github; Code Project article). GSerjo的Extended Thread Pool看起来也不错,但是我在移动设备上试图避免使用很多依赖项.我在Xamarim thread编写了一些简单的测试.我可能错过了其他100个线程池实现,但到目前为止我对SmartThreadPool感到满意.使用WINDOWS_PHONE模式在MonoTouch下编译.
解决方法
So my question: is this a bug in Mono/MonoTouch?
不必要.我怀疑它只是线程池不愿意每500毫秒启动一个以上的新线程.请注意,您看到第一个任务立即启动.只有在那之后你才会看到延迟.
如果你在.NET 4.5上使用更多的任务,你会看到类似的东西,除了每秒开始的“大块”线程.
假设在MonoTouch中可用,您可能会发现调用ThreadPool.SetMinThreads
会有所帮助.