Real purpose of providing TaskScheduler option through ParallelOptions parameter in Parallel class APIs

坚强是说给别人听的谎言 提交于 2020-01-04 14:00:56

问题


I have a windows C# WinForms application. I'm confused by the way the default task scheduler is behaving for parallel class in task parallel library. When I call Parallel.For inside ParallelForEach method I was expecting the numbers to get printed in jumbled fashion in output window through Console.WriteLine statement inside "Method1" method.

Since I'm not passing any ParallelOptions to configure the scheduler for Parallel class it should be using default task scheduler but numbers are getting printed in serial fashion like 0,1,2,3,.....49. This gives me an impression that all the tasks which are getting executed are running on UI synchronization context in serial fashion one by one. I also verified this by updating the text property of UI text box with value of i and it didn't throw me an InvalidOperationException which happens in case of thread-pool thread.

But if I uncomment the first statement inside Method1 function to simulate long running task the output gets jumbled. Why is the CLR is making this decision to use the UI thread to run all those 50 tasks? Why is the CLR is making this decision on my behalf when I have not asked it to do so just on the basis of the fact that initially my task is small compute bound task? How does the CLR really evaluate the fact that a particular method will take long time to execute or small time to execute?

Hardware information: My computer is a Windows Server 2008 box with four cores.

namespace WindowsFormsApplication1
{
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Schedulers;
using System.Windows.Forms;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        ParallelForEach();
    }

    private void ParallelForEach()
    {
        Console.WriteLine("With default task scheduler");
        Parallel.For(0, 50, i => Method1(i));
     }

    private void Method1(int i)
    {
        //System.Threading.Thread.Sleep(2000);
        //textBox1.Text = i.ToString();
        Console.WriteLine(i);
        //do some work   
    }
}
}

回答1:


By default, Parallel.For() uses the default TaskScheduler (which uses the ThreadPool) and also the current thread (it has to be blocked until all iterations are complete, so it might as well do some useful work, instead of just waiting). So, if you have a small number iterations that finish fast, it's possible that the whole loop will execute on the current loop, before all the Tasks that are scheduled to the TaskScheduler even start. This explains the behavior you're seeing in both cases.


Note that you shouldn't block the UI thread for a long period of time, doing that freezes the UI of the application. This implies that you shouldn't use Parallel.For() on the UI thread.



来源:https://stackoverflow.com/questions/35684196/real-purpose-of-providing-taskscheduler-option-through-paralleloptions-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!