C# 为什么线程不工作?

C# 为什么线程不工作?,c#,.net,multithreading,.net-4.0,parallel-processing,C#,.net,Multithreading,.net 4.0,Parallel Processing,这是我的密码: using System; using System.Collections; using System.Collections.Generic; using System.Collections.Concurrent; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.IO; using System.IO.MemoryMappedFiles; na

这是我的密码:

using System;

using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;

using System.Threading;
using System.Threading.Tasks;

using System.IO;
using System.IO.MemoryMappedFiles;

namespace CopyFile
{
class Program
{
    static void Main()
    {
        long length = 0;
        byte[] buffer;
        string source_path, dest_path;
        source_path = Console.ReadLine();
        dest_path = Console.ReadLine();
        FileInfo fi = new FileInfo(source_path);
        length = (int)fi.Length;
        // Create disk file
        using (FileStream fs = File.Create(dest_path))
        {
            fs.Close();
        }
        // Create unnamed MMF
        var mmf1 = MemoryMappedFile.CreateFromFile(source_path, FileMode.OpenOrCreate, null, length);
        // Create reader to MMF
        var reader = mmf1.CreateViewAccessor(0, length, MemoryMappedFileAccess.Read);
        // Create unnamed MMF
        var mmf2 = MemoryMappedFile.CreateFromFile(dest_path, FileMode.Create, null, length);
        // Create writer to MMF
        var writer = mmf2.CreateViewAccessor(0, length, MemoryMappedFileAccess.Write);

        int read_block = int.Parse(Math.Min(length, 512 * 1024).ToString());//4k
        int end_read_block = int.Parse(length.ToString()) % read_block;

        int[] offset_array = new int[int.Parse((length - read_block).ToString()) / read_block];
        for (int offset = 0,i=0; i < int.Parse((length - read_block).ToString()) / read_block; i++,offset += read_block)
        {
            offset_array[i] = offset;
        }

        /*
        Parallel.ForEach<int>(offset_array, offset =>
        {
            // Read from MMF
            buffer = new byte[read_block];
            reader.ReadArray<byte>(offset, buffer, 0, read_block);
            // Write to MMF
            writer.WriteArray<byte>(offset, buffer, 0, read_block);
        });
         */
        foreach (int offset in offset_array)
        {
            // Read from MMF
            buffer = new byte[read_block];
            reader.ReadArray<byte>(offset, buffer, 0, read_block);
            // Write to MMF
            writer.WriteArray<byte>(offset, buffer, 0, read_block);
        }

        buffer = new byte[end_read_block];
        reader.ReadArray<byte>(length - end_read_block, buffer, 0, end_read_block);
        // Write to MMF
        writer.WriteArray<byte>(length - end_read_block, buffer, 0, end_read_block);

    }
}
}
使用系统;
使用系统集合;
使用System.Collections.Generic;
使用System.Collections.Concurrent;
使用System.Linq;
使用系统线程;
使用System.Threading.Tasks;
使用System.IO;
使用System.IO.MemoryAppedFile;
命名空间复制文件
{
班级计划
{
静态void Main()
{
长长度=0;
字节[]缓冲区;
字符串源路径、目标路径;
source_path=Console.ReadLine();
dest_path=Console.ReadLine();
FileInfo fi=新的FileInfo(源路径);
长度=(int)fi.length;
//创建磁盘文件
使用(FileStream fs=File.Create(dest_path))
{
fs.Close();
}
//创建未命名的MMF
var mmf1=MemoryMappedFile.CreateFromFile(源路径,FileMode.OpenOrCreate,null,长度);
//创建读卡器到MMF
var reader=mmf1.CreateViewAccessor(0,长度,MemoryMappedFileAccess.Read);
//创建未命名的MMF
var mmf2=MemoryMappedFile.CreateFromFile(dest_path,FileMode.Create,null,length);
//创建MMF的写入程序
var writer=mmf2.CreateViewAccessor(0,长度,MemoryMappedFileAccess.Write);
int read_block=int.Parse(Math.Min(长度512*1024).ToString());//4k
int end_read_block=int.Parse(length.ToString())%read_block;
int[]offset_array=new int[int.Parse((length-read_block).ToString())/read_block];
对于(int offset=0,i=0;i
{
//从MMF读取
缓冲区=新字节[读取块];
ReadArray(偏移量、缓冲区、0、读取块);
//写入MMF
writer.WriteArray(偏移量、缓冲区、0、读块);
});
*/
foreach(偏移量数组中的int偏移量)
{
//从MMF读取
缓冲区=新字节[读取块];
ReadArray(偏移量、缓冲区、0、读取块);
//写入MMF
writer.WriteArray(偏移量、缓冲区、0、读块);
}
缓冲区=新字节[结束读取块];
ReadArray(长度-结束读取块,缓冲区,0,结束读取块);
//写入MMF
writer.WriteArray(长度-结束读取块、缓冲区、0、结束读取块);
}
}
}
我尝试复制一个文件并将其粘贴到另一个位置 它正在工作

但是当我尝试使用Parallel.foreach或Parallel.for复制一个文件时 复制的文件与源文件不同

(I.foreach节)

我不明白为什么

感谢您的代码中的

Parallel.ForEach<int>(offset_array, offset =>
{
    // Read from MMF
    buffer = new byte[read_block];
    reader.ReadArray<byte>(offset, buffer, 0, read_block);
    // Write to MMF
    writer.WriteArray<byte>(offset, buffer, 0, read_block);
});
这将允许所有线程都有自己的本地缓冲区


尽管如此,任何实例方法(ReadArray/WriteArray)都不能保证线程安全。换句话说,即使您解决了缓冲区问题,也不能保证一切正常。

您复制文件的方法不好。除了Joachim Isaksson描述的问题之外,问题在于您同时从多个线程访问文件流。这意味着一个线程T1读取数据,然后调度程序将控制传递给线程T2,线程T2读取数据,然后将数据写入目标。当控件返回T1并写入读取数据时,您将得到一个损坏的文件。
没有理由使用并发来复制文件,因为CPU不是此操作的瓶颈。您不会得到更快的结果,只会浪费CPU周期。

它将如何工作?如果有多个线程写入文件,您将无法按顺序写入该文件。他的代码的基本问题是,他试图通过使用多个线程访问同一数据流来更快地复制文件。虽然您的答案指向一个问题,但它并不能解决更大的问题。@NikolaRadosavljević虽然不太可能,但这是我们正在读/写的内存映射文件。如果页面被调出,在等待pagein时让另一个线程接管并复制下一页实际上可能会加快操作。尽管在实践中同意,但这可能不会加快任何速度。@NikolaRadosavljević在阅读您的输入并仔细检查文档后更新了我的答案。好电话。
Parallel.ForEach<int>(offset_array, offset =>
{
    // Read from MMF
    byte[] buffer = new byte[read_block];
    reader.ReadArray<byte>(offset, buffer, 0, read_block);
    // Write to MMF
    writer.WriteArray<byte>(offset, buffer, 0, read_block);
});