Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

The following code should (at least in my opinion) create 100 Tasks, which are all waiting in parallel (that's the point about concurrency, right :D ?) and finish almost at the same time. I guess for every Task.Delay a Timerobject is created internally.

public static async Task MainAsync() {

    var tasks = new List<Task>();
    for (var i = 0; i < 100; i++) {
        Func<Task> func = async () => {
            await Task.Delay(1000);
            Console.WriteLine("Instant");
        };
        tasks.Add(func());
    }
    await Task.WhenAll(tasks);
}

public static void Main(string[] args) {
    MainAsync().Wait();
}

But! When I run this on Mono I get very strange behavior:

  • The Tasks do not finish at the same time, there are huge delays (probably about 500-600ms)
  • In the console mono shows a lot of created threads:

Loaded assembly: /Users/xxxxx/Programming/xxxxx/xxxxxxxxxx/bin/Release/xxxxx.exe

Thread started: #2

Thread started: #3

Thread started: #4

Thread started: #5

Thread started: #6

Thread started: #7

Thread finished: #3 <-- Obviously the delay of 1000ms finished ?

Thread finished: #2 <-- Obviously the delay of 1000ms finished ?

Thread started: #8

Thread started: #9

Thread started: #10

Thread started: #11

Thread started: #12

Thread started: #13

... you get it.

Is this actually a bug ? Or do I use the library wrong ?

[EDIT] I tested a custom sleep method using Timer:

    public static async Task MainAsync() {
        Console.WriteLine("Started");
        var tasks = new List<Task>();
        for (var i = 0; i < 100; i++) {
            Func<Task> func = async () => {
                await SleepFast(1000);
                Console.WriteLine("Instant");
            };
            tasks.Add(func());
        }
        await Task.WhenAll(tasks);
        Console.WriteLine("Ready");
    }

    public static Task SleepFast(int amount) {
        var source = new TaskCompletionSource<object>();
        new Timer(state => {
            var oldSrc = (TaskCompletionSource<object>)state;
            oldSrc.SetResult(null);
        }, source, amount, 0);
        return source.Task;
    }

This time, all tasks completed instantaneously. So, I think it's a really bad implementation or a bug.

[Edit2] Just FYI: I've tested the original code (using Task.Delay) on .NET using Windows 8.1 now and it ran as expected (1000 Tasks, waiting for 1 second in parallel and finishing).

So the answer is: Mono's impl. of (some) methods is not perfect. In general Task.Delay does not start a thread and even a lot of them should not create multiple threads.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
501 views
Welcome To Ask or Share your Answers For Others

1 Answer

The Task library is designed more for managing blocking tasks without blocking an entire workflow (task asynchronism, confusingly called "task parallel" by Microsoft), and not for doing large blocks of concurrent computation (parallel execution).

The task library uses a scheduler and queues jobs ready for execution. When jobs are run, they will do so on a thread-pool thread, and these are very limited in number. There is logic to expand the thread count, but unless you have hundreds of CPU cores, it's going to stay a low number.

So to answer the question, some of your tasks are queued up waiting for a thread from the pool, while the other delayed tasks have been issued by the scheduler.

The scheduler and thread-pool logic can be changed at runtime, but if you are trying to get lots of computation done quickly Task isn't right for the job. If you want to deal with lots of slow resources (like disk, database, or internet resources) Task may help keep an app responsive.

If you just want to learn about Task try these:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...