Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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# 为什么多线程比单线程慢?_C#_Multithreading - Fatal编程技术网

C# 为什么多线程比单线程慢?

C# 为什么多线程比单线程慢?,c#,multithreading,C#,Multithreading,我知道有几个人问了一个类似的问题,但我找不到任何能让我理解为什么速度较慢的回答 因此,我制作了一个小控制台程序,以便于我自己理解VisualStudio2013中的线程对象。我的CPU是一个Intel Core i7,可以使用多线程 我的代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Syste

我知道有几个人问了一个类似的问题,但我找不到任何能让我理解为什么速度较慢的回答

因此,我制作了一个小控制台程序,以便于我自己理解VisualStudio2013中的线程对象。我的CPU是一个Intel Core i7,可以使用多线程

我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {

        static TimeSpan MTTime;
        static TimeSpan STTime;

        static void Main(string[] args)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();


            Console.WriteLine(Environment.NewLine + "---------------Multi Process-------------" + Environment.NewLine);

            Thread th1 = new Thread(new ParameterizedThreadStart(Process));
            Thread th2 = new Thread(new ParameterizedThreadStart(Process));
            Thread th3 = new Thread(new ParameterizedThreadStart(Process));
            Thread th4 = new Thread(new ParameterizedThreadStart(Process));

            th1.Start("A");
            th2.Start("B");
            th3.Start("C");
            th4.Start("D");

            th1.Join();
            th2.Join();
            th3.Join();
            th4.Join();

            stopwatch.Stop();
            MTTime = stopwatch.Elapsed ;

            Console.WriteLine(Environment.NewLine + "---------------Single Process-------------" + Environment.NewLine);


            stopwatch.Reset();
            stopwatch.Start();

            Process("A");
            Process("B");
            Process("C");
            Process("D");

            stopwatch.Stop();
            STTime = stopwatch.Elapsed;

            Console.Write(Environment.NewLine + Environment.NewLine + "Multi  : "+ MTTime + Environment.NewLine + "Single : " + STTime);


            Console.ReadKey();
        }

        static void Process(object procName)
        {
            for (int i = 0; i < 100; i++)
            {
                Console.Write(procName);
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用系统线程;
使用系统诊断;
命名空间控制台应用程序1
{
班级计划
{
静态时间跨度MTTime;
静态时间间隔;
静态void Main(字符串[]参数)
{
秒表秒表=新秒表();
秒表。开始();
Console.WriteLine(Environment.NewLine+“--------------多进程--------------------”+Environment.NewLine);
Thread th1=新线程(新的参数化线程启动(进程));
Thread th2=新线程(新的参数化线程启动(进程));
th3线程=新线程(新参数化的threadstart(进程));
Thread th4=新线程(新的参数化线程启动(进程));
th1.启动(“A”);
th2.启动(“B”);
th3.启动(“C”);
th4.启动(“D”);
th1.Join();
th2.Join();
th3.Join();
th4.Join();
秒表;
MTTime=秒表。已用时间;
Console.WriteLine(Environment.NewLine+“--------------单进程--------------------”+Environment.NewLine);
秒表复位();
秒表。开始();
过程(“A”);
过程(“B”);
过程(“C”);
过程(“D”);
秒表;
STTime=秒表。已用时间;
Console.Write(Environment.NewLine+Environment.NewLine+“Multi:”+MTTime+Environment.NewLine+“Single:”+STTime);
Console.ReadKey();
}
静态无效进程(对象名称)
{
对于(int i=0;i<100;i++)
{
Console.Write(procName);
}
}
}
}
结果图像:

我们可以清楚地看到,多踏板的过程是完全随机的,单个踏板只是一个接一个地进行所有的按压,但我不认为这对速度有影响


起初,我认为我的线程比运行程序所需的进程大,但在换了一个更大的进程后,单线程仍然是最快的。那么,我是否错过了多线程的一个概念?或者说速度较慢是正常的?

请注意,
进程
写入控制台(基本上不做其他事情),而控制台的输出(这里作为一种共享资源)速度较慢,需要与其他线程同步

据我所知,您使用的并行化产生了巨大的开销,但没有获得任何加速,因为线程显然一直在等待另一个进程完成对控制台的写入。

来自官方文档

使用这些流的I/O操作是同步的,这意味着 多个线程可以读取或写入流。这 意味着通常是异步的方法,例如 TextReader.ReadLineAsync,如果对象 表示控制台流

这意味着控制台类处理线程同步,因此,如果线程A和线程B试图写入控制台,控制台将处理它们,一次只能有一个线程能够写入。它背后的处理逻辑是花费更长时间的原因


更新

我建议您再考虑一件事:您正在承受线程创建和连接的开销。此外,通过使用threadpool,您可能会获得轻微的性能升级,请查看以下内容:


好的!感谢阿萨和科多,让我把心思放在正确的地方!我最终制作了一个小的控制台程序,它可以非常清晰地显示每一件事。最后,当使用繁重的处理程序时,多重读取速度要快得多。只要阅读我的代码,你就会轻松理解

结果:

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        //Timer for speed guidance
        static Stopwatch stopwatch;
        //Data i use for generate time
        static List<int> timeData;
        static void Main(string[] args)
        {
            stopwatch = new Stopwatch();
            timeData = new List<int> { 1000, 800, 200, 700, 600, 300, 800, 100, 200, 300, 655, 856, 695, 425 };

            ////-------------------------- SINGLE THREAD ------------------------------/////
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("             Single Threading Process            ");
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("   Process Time        Thread ID                 ");
            Console.WriteLine("-------------------------------------------------");
            stopwatch.Reset();
            stopwatch.Start();
            //For each normal that use only 1 thread
            foreach(int i in timeData)
            {
                Process(i);
            }

            stopwatch.Stop();
            //Total time that the program take for making the process happen
            Console.WriteLine("*Total : " + stopwatch.Elapsed );

            ////-------------------------- Mulit Multiple ------------------------------/////

            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("             Multi Threading Process            ");
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("   Process Time        Thread ID                 ");
            Console.WriteLine("-------------------------------------------------");
            stopwatch.Reset();
            stopwatch.Start();
            //for each thats use Multiple thread fr the process (can be made with parallel.invoke or Task Library or Thread Library)
            Parallel.ForEach(timeData, (i) => Process(i));
            //Total time that the program take for making the process happen
            Console.WriteLine("*Total : " + stopwatch.Elapsed);
            Console.WriteLine("-------------------------------------------------");
            Console.ReadKey();
        }

        // Methode for sumulating long processing
        static void Process( int time)
        {
            stopwatch.Reset();
            stopwatch.Start();
            //sleep time simulate the IO portion of the process
            Thread.Sleep(time);
            // The loop simulate de algoritme type of precessing
            for (int i = 0; i < time*1000000; i++){}
            stopwatch.Stop();
            Console.WriteLine( stopwatch.Elapsed + "         " + Thread.CurrentThread.ManagedThreadId.ToString());          
        }


    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用系统线程;
使用系统诊断;
命名空间控制台应用程序1
{
班级计划
{
//速度引导计时器
静态秒表;
//我用于生成时间的数据
静态列表时间数据;
静态void Main(字符串[]参数)
{
秒表=新秒表();
timeData=新列表{1000、800、200、700、600、300、800、100、200、300、655、856、695、425};
////--------------------------单线------------------------------/////
Console.WriteLine(“-------------------------------------------------------------”;
Console.WriteLine(“单线程进程”);
Console.WriteLine(“-------------------------------------------------------------”;
WriteLine(“进程时间线程ID”);
Console.WriteLine(“-------------------------------------------------------------”;
秒表复位();
秒表。开始();
//对于仅使用1个线程的每个法线
foreach(时间数据中的int i)
{
过程(一);
}
秒表;
//程序执行该过程所需的总时间
控制台写入线(“*总计:+秒表已用);
////--------------------------多重------------------------------/////
Console.Write(procName);