Real purpose of providing TaskScheduler option thr

2019-07-11 18:42发布

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条回答
做个烂人
2楼-- · 2019-07-11 18:55

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.

查看更多
登录 后发表回答