Task.Factory.StartNew() 在 Mono/MonoTouch 下延迟 [英] Task.Factory.StartNew() Delay Under Mono / MonoTouch

查看:19
本文介绍了Task.Factory.StartNew() 在 Mono/MonoTouch 下延迟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Mono 和 MonoTouch 下,我在调用之间看到大约 500 毫秒的延迟:

Under Mono and MonoTouch, I am seeing an approx 500 millisecond delay between when I call:

StartNew(Action<object> action, object state, CancellationToken cancellationToken, 
    TaskCreationOptions creationOptions, TaskScheduler scheduler);

当工作代码真正开始执行时.

and when the worker code actually starts executing.

我创建了一个测试来证明这一点:

I created a test to show this:

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 下的输出:

Output under Mono on Mac:

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 毫秒以下,延迟就会减少.例如,将工作线程 Thread.Sleep(2000) 更改为 Thread.Sleep(50):

It is as if Mono wants to wait up to 500 msec to reuse an existing thread before spawing a new one. If I decrease the worker time below 500 msec, the delay decreases. For example, changing the worker Thread.Sleep(2000) to 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 下,工作代码开始之前没有延迟:

But under MS Framework 4.0, no large delay before worker code starts:

...
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.我实际上在我的真实应用中使用了最大并发调度程序.

Before I submit a bug report on Mono, I wanted to sanity check that I am not missing some tweak I need to make on Mono or using Task.Factory wrong. I am actually using a max concurrency scheduler in my real app.

所以我的问题是:这是 Mono/MonoTouch 中的错误吗?

So my question: is this a bug in Mono/MonoTouch?

更新:我已从使用 Mono* 下的 ThreadPool 切换到 Ami Bar 的智能线程池 (github; 代码项目文章).GSerjo 的 Extended Thread Pool 看起来也不错,但有很多依赖我试图避免在手机上.我在 Xamarim 线程 上写了一些简单的测试.我可能错过了 100 个其他线程池实现,但到目前为止我对 SmartThreadPool 很满意.使用WINDOWS_PHONE模式在MonoTouch下编译.

Update: I've switched from using ThreadPool under Mono* to Ami Bar's Smart Thread Pool (github; Code Project article). GSerjo's Extended Thread Pool also looked nice, but had alot of dependencies that I was trying to avoid on mobile. I wrote up some of my simple testing at a Xamarim thread. I probably missed 100 other thread pool implementations, but I've been happy with SmartThreadPool so far. Use WINDOWS_PHONE mode to compile under MonoTouch.

推荐答案

所以我的问题是:这是 Mono/MonoTouch 中的错误吗?

So my question: is this a bug in Mono/MonoTouch?

不一定.我怀疑只是线程池不愿意每 500 毫秒启动一个以上的新线程.请注意,您会看到 first 任务几乎立即启动.只有在那之后,您才会看到延迟.

Not necessarily. I suspect it's just the thread pool being unwilling to start more than one new thread every 500ms. Note that you're seeing the first task start up pretty much instantly. It's only after that that you're seeing a delay.

如果您在 .NET 4.5 上使用更多任务,您会看到类似的东西,除了每秒启动的块"线程.

If you use more tasks on .NET 4.5, you'll see something similar, except with "chunks" of threads starting each second.

您可能会发现调用 ThreadPool.SetMinThreads 有帮助,假设它在 MonoTouch 中可用.

You may find that calling ThreadPool.SetMinThreads helps, assuming that's available in MonoTouch.

这篇关于Task.Factory.StartNew() 在 Mono/MonoTouch 下延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆