When should Task.ContinueWith be called with TaskScheduler.Current as an argument?

前端 未结 4 459
悲&欢浪女
悲&欢浪女 2021-02-02 15:03

We are using this code snippet from StackOverflow to produce a Task that completes as soon as the first of a collection of tasks completes successfully. Due to the non-linear na

4条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-02-02 15:26

    I most certainly don't think I am capable of providing bullet proof answer but I will give my five cents.

    What is a specific example of a case where it would be best to pass TaskScheduler.Current into ContinueWith(), as opposed to TaskScheduler.Default?

    Imagine you are working on some web api that webserver naturally makes multithreaded. So you need to compromise your parallelism because you don't want to use all the resources of your webserver, but at the same time you want to speed up your processing time, so you decide to make custom task scheduler with lowered concurrency level because why not.

    Now your api needs to query some database and order the results, but these results are millions so you decide to do it via Merge Sort(divide and conquer), then you need all your child tasks of this algorithm to be complient with your custom task scheduler (TaskScheduler.Current) because otherwise you will end up taking all the resources for the algorithm and your webserver thread pool will starve.

    When to use TaskScheduler.Current, TaskScheduler.Default, TaskScheduler.FromCurrentSynchronizationContext(), or some other TaskScheduler

    • TaskScheduler.FromCurrentSynchronizationContext() - Specific for WPF, Forms applications UI thread context, you use this basically when you want to get back to the UI thread after being offloaded some work to non-UI thread

    example taken from here

    private void button_Click(…) 
    { 
        … // #1 on the UI thread 
        Task.Factory.StartNew(() => 
        { 
            … // #2 long-running work, so offloaded to non-UI thread 
        }).ContinueWith(t => 
        { 
            … // #3 back on the UI thread 
        }, TaskScheduler.FromCurrentSynchronizationContext()); 
    }
    
    • TaskScheduler.Default - Almost all the time when you don't have any specific requirements, edge cases to collate with.
    • TaskScheduler.Current - I think I've given one generic example above, but in general it should be used when you have either custom scheduler or you explicitly passed TaskScheduler.FromCurrentSynchronizationContext() to TaskFactory or Task.StartNew method and later you use continuation tasks or inner tasks (so pretty damn rare imo).

提交回复
热议问题