Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过并行类API中的ParallelOptions参数提供TaskScheduler选项的真正目的_C#_.net_C# 4.0_Task Parallel Library_Task - Fatal编程技术网

C# 通过并行类API中的ParallelOptions参数提供TaskScheduler选项的真正目的

C# 通过并行类API中的ParallelOptions参数提供TaskScheduler选项的真正目的,c#,.net,c#-4.0,task-parallel-library,task,C#,.net,C# 4.0,Task Parallel Library,Task,我有一个windows C#WinForms应用程序。对于任务并行库中并行类的默认任务调度器的行为方式,我感到困惑。当我调用Parallel.ForinsideParallelForEach方法时,我希望通过控制台在输出窗口中以混乱的方式打印数字。WriteLine语句位于“Method1”方法中 因为我没有传递任何ParallelOptions来配置并行类的调度程序,所以它应该使用默认的任务调度程序,但是数字是以串行方式打印的,比如0,1,2,3,…49。这给我的印象是,正在执行的所有任务都是

我有一个windows C#WinForms应用程序。对于任务并行库中并行类的默认任务调度器的行为方式,我感到困惑。当我调用
Parallel.For
inside
ParallelForEach
方法时,我希望通过
控制台在输出窗口中以混乱的方式打印数字。WriteLine
语句位于“Method1”方法中

因为我没有传递任何
ParallelOptions
来配置并行类的调度程序,所以它应该使用默认的任务调度程序,但是数字是以串行方式打印的,比如0,1,2,3,…49。这给我的印象是,正在执行的所有任务都是以串行方式在UI同步上下文上逐个运行的。我还通过用I值更新UI文本框的text属性来验证这一点,它没有向我抛出
invalidoOperationException
,这在线程池线程的情况下会发生

但是如果我取消注释
Method1
函数中的第一条语句以模拟长时间运行的任务,那么输出就会变得混乱。为什么CLR决定使用UI线程来运行所有这50个任务?为什么CLR代表我做出这个决定,而我并没有要求它这么做,只是因为我的任务最初是小型计算任务?CLR如何真正评估特定方法执行时间长或执行时间短这一事实

硬件信息:我的电脑是一个Windows Server 2008机箱,有四个内核

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   
    }
}
}

默认情况下,
Parallel.For()
使用默认的
TaskScheduler
(它使用
ThreadPool
)和当前线程(它必须被阻止,直到所有迭代完成,所以它可能需要做一些有用的工作,而不是等待)。因此,如果有少量迭代快速完成,则整个循环可能会在当前循环上执行,甚至在
任务调度器
调度的所有
任务
启动之前。这解释了你在这两种情况下看到的行为



请注意,您不应该长时间阻塞UI线程,这样做会冻结应用程序的UI。这意味着您不应该在UI线程上使用
Parallel.For()

相关-。您可能会尝试深入研究,但我实际上怀疑是否存在一些超级聪明的算法(一些启发式算法依赖于内部和外部因素,但仅此而已),尽管有可能部分算法隐藏在外部实现方法中,在这种情况下,.NET内核可能更有用-,我怀疑SynchronizationContext是否与您遇到的行为有关。最可能的情况是,Paraller.For尝试在原始线程上执行部分任务,并且仅在需要超过特定时间的情况下才开始使用其他线程。您的意思是-线程完成迭代的速度太快,它会很快拿起下一个任务?在另一个例子中,另一个线程拾取下一个任务,而第一个线程被阻塞在
Sleep()
?@shay_uuuuu某种程度上,除了
并行之外。对于(0,50,…)
,并不意味着有50个
任务。因此,在
任务
被分配线程之前,主线程完成了所有迭代。@svick我也有类似的印象,但我只是在读到ParallelOptions类时感到困惑,该类可以作为参数传递给Parallel.For方法。ParallelOptions类有一个属性“TaskScheduler”,用于选择所选的指定TaskScheduler。其默认值为“TaskScheduler.default”。现在我明白了你的观点,主线程的这种使用哲学适用于并行类的所有方法,而不管我们如何配置与之相关的调度器。我又做了一件事,将循环计数器增加到500,然后输出变得混乱:)@shay_uuu只是为了添加svick提到的内容。作为默认行为,任务调度器通常调度与计算机上CPU核数量相同的任务(在我的例子中是4个)。这可以通过ParallelOptions类进行配置,ParallelOptions类可以作为参数传递给Parallel.For method。实际上,这是一个很好的例子,说明基于任务的并行不仅比基于线程的并行容易,而且效率更高!(第一个示例,没有
Sleep()