Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.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_C# 4.0_Task Parallel Library_Task - Fatal编程技术网

C# 如何使用类任务进行并行处理

C# 如何使用类任务进行并行处理,c#,multithreading,c#-4.0,task-parallel-library,task,C#,Multithreading,C# 4.0,Task Parallel Library,Task,我是一名初级程序员,我正在努力解决一项任务。我正在使用c#.net 4.0浏览文件夹,选择所有*.xml文件,并将每个文件写入具有新扩展名*.bin的新文件夹。对于编写之前的每个文件,我都在应用另一个程序员编写的算法,我不知道它的实现 所以我读取了*.xml文件,对其进行反序列化并将其写入新的*.bin文件。当我没有使用并行编程时,我有1分钟的时间处理2000个文件。现在我决定将并行编程应用于任务。现在我为每个文件创建新任务(所有处理(读-反序列化-写)都在一个任务中),现在我有40秒。但我认为

我是一名初级程序员,我正在努力解决一项任务。我正在使用c#.net 4.0浏览文件夹,选择所有*.xml文件,并将每个文件写入具有新扩展名*.bin的新文件夹。对于编写之前的每个文件,我都在应用另一个程序员编写的算法,我不知道它的实现

所以我读取了*.xml文件,对其进行反序列化并将其写入新的*.bin文件。当我没有使用并行编程时,我有1分钟的时间处理2000个文件。现在我决定将并行编程应用于任务。现在我为每个文件创建新任务(所有处理(读-反序列化-写)都在一个任务中),现在我有40秒。但我认为并行编程帮助我将时间缩短到25-30秒

请给出你的意见,我做错了什么,以及我如何认识到这一点。谢谢

byte[] buffer;
using (Stream stream = new FileInfo(file).OpenRead())
{
    buffer = new byte[stream.Length];
    stream.Read(buffer, 0, (int)stream.Length);
}

foreach (var culture in supportedCultures)
{
    CultureInfo currentCulture = culture;
    Tasks.Add(Task.Factory.StartNew(() =>
    {
        var memoryStream = new MemoryStream(buffer);
        Task<object> serializeTask = Task.Factory.StartNew(() =>
        {
            return typesManager.Load(memoryStream, currentCulture);
        }, TaskCreationOptions.AttachedToParent);

        string currentOutputDirectory = null;
        if (outputDirectory != null)
        {
            currentOutputDirectory = outputDirectory.Replace(PlaceForCultureInFolderPath,
                                                                 currentCulture
                                                                     .ToString());
            Directory.CreateDirectory(currentOutputDirectory);
        }

        string binFile = Path.ChangeExtension(Path.GetFileName(file), ".bin");
        string binPath = Path.Combine(
            currentOutputDirectory ?? Path.GetDirectoryName(file),
            binFile);

        using (FileStream outputStream = File.OpenWrite(binPath))
        {
            try
            {
                new BinaryFormatter().Serialize(outputStream,serializeTask.Result);
            }
            catch (SerializationException e)
            {
                ReportCompilationError(e.Message, null);
            }
        }
    }));
}
byte[]缓冲区;
使用(Stream=newfileinfo(file.OpenRead())
{
缓冲区=新字节[stream.Length];
读取(缓冲区,0,(int)stream.Length);
}
foreach(supportedCultures中的var区域性)
{
CultureInfo currentCulture=区域性;
Tasks.Add(Task.Factory.StartNew(()=>
{
var memoryStream=新的memoryStream(缓冲区);
Task serialized Task=Task.Factory.StartNew(()=>
{
返回typesManager.Load(memoryStream,currentCulture);
},TaskCreationOptions.AttachedToParent);
字符串currentOutputDirectory=null;
if(outputDirectory!=null)
{
currentOutputDirectory=outputDirectory.Replace(PlaceForCultureInFolderPath,
当前文化
.ToString());
CreateDirectory(currentOutputDirectory);
}
字符串binFile=Path.ChangeExtension(Path.GetFileName(文件),“.bin”);
字符串binPath=Path.Combine(
currentOutputDirectory??Path.GetDirectoryName(文件),
binFile);
使用(FileStream outputStream=File.OpenWrite(binPath))
{
尝试
{
新的BinaryFormatter().Serialize(outputStream,serializeTask.Result);
}
捕获(序列化异常)
{
报表编译错误(e.Message,null);
}
}
}));
}

在看不到代码或不知道任务真正在做什么的情况下,我们所能做的就是提供一些相当一般的建议和诊断

您的代码是CPU绑定还是IO绑定?(您应该能够通过查看性能监视器和运行代码时CPU的繁忙程度来判断这一点。)

如果您的代码是IO绑定的,并且在一个物理非SSD驱动器上有多个文件,那么并行工作很可能会使情况变得更糟,因为您会迫使驱动器头在整个位置上不断打点


如果您的代码是CPU受限的,那么并行化应该会有所帮助(因为这些听起来像是独立的任务)——同样,您应该能够通过先运行代码而不进行并行化,然后再进行并行化来判断这一点,在这两种情况下,请查看CPU图。您可能会认为,在串行版本中,一次只有一个CPU“忙”,而在并行版本中,所有CPU都应该忙。

在看不到代码或不知道任务真正在做什么的情况下,我们所能做的就是提供一些相当一般的建议和诊断

您的代码是CPU绑定还是IO绑定?(您应该能够通过查看性能监视器和运行代码时CPU的繁忙程度来判断这一点。)

如果您的代码是IO绑定的,并且在一个物理非SSD驱动器上有多个文件,那么并行工作很可能会使情况变得更糟,因为您会迫使驱动器头在整个位置上不断打点

如果您的代码是CPU受限的,那么并行化应该会有所帮助(因为这些听起来像是独立的任务)——同样,您应该能够通过先运行代码而不进行并行化,然后再进行并行化来判断这一点,在这两种情况下,请查看CPU图。在串行版本中,一次只有一个CPU“忙”,而在并行版本中,所有CPU都应该忙。

但这并不能保证每个任务都有一个新线程,因为它使用可用的线程,只调度作业或将任务分配给任何可用的线程。因此,我建议您使用
Parallel.ForEach

var options = new ParallelOptions { MaxDegreeOfParallelism = 2 // or more };
Parallel.ForEach ( list, options, a=> { } );

但这并不能保证每个任务都有一个新线程,因为它使用可用的线程,只调度作业或将任务分配给任何可用的线程。因此,我建议您使用
Parallel.ForEach

var options = new ParallelOptions { MaxDegreeOfParallelism = 2 // or more };
Parallel.ForEach ( list, options, a=> { } );

首先。不能保证TPL会对性能造成任何影响。
正如Jon所说,写入HDD会降低性能,除非操作系统缓存这些文件以供以后的顺序写入。当然,缓存大小有它的限制

第二。默认调度程序面向使用CPU核心,因此可能只有几个任务并行处理,其他任务在队列中等待。您可以通过显式设置
ParallelOptions.MaxDegreeOfParallelism
或在查询中调用
WidthDegreeOfParallelism()
来更改此默认值。仍然是调度程序决定并行运行多少任务


首先,在.net中有一个关于多线程的免费软件。不能保证TPL会对性能造成任何影响。
正如Jon所说,写入HDD会降低性能,除非操作系统缓存这些文件以供以后的顺序写入。当然,缓存大小有它的限制

第二。默认调度程序面向使用CPU核心,因此可能只有几个任务并行处理,其他任务在队列中等待。您可以通过显式设置
Paralle来更改此默认值