C# 一次例外,另一次不例外

C# 一次例外,另一次不例外,c#,multithreading,out-of-memory,C#,Multithreading,Out Of Memory,我使用多线程将文件复制到另一个位置。我从需要的字节数组和dispose流中提取数据。在本例中,我使用7个线程复制3gb文件。第一个线程可以获取字节数组,但在第二个线程出现异常“System.OutOfMemoryException” public void Begin() { FileStream stream = new FileStream(pathToFile, FileMode.Open); stream.Position = (threNmb - 1) * 536870

我使用多线程将文件复制到另一个位置。我从需要的字节数组和dispose流中提取数据。在本例中,我使用7个线程复制3gb文件。第一个线程可以获取字节数组,但在第二个线程出现异常“System.OutOfMemoryException”

public void Begin()
{
    FileStream stream = new FileStream(pathToFile, FileMode.Open);
    stream.Position = (threNmb - 1) * 536870912;
    BinaryReader reader = new BinaryReader(stream);
    for (long i = 0; i < (length); i++)
    {
        source.Add(reader.ReadByte());//gives exception at i=134217728
    }
    reader.Dispose();
    reader.Close();
    stream.Dispose();
    stream.Close();
}
public void Begin()
{
FileStream stream=新的FileStream(路径文件,FileMode.Open);
流位置=(threNmb-1)*536870912;
BinaryReader=新的BinaryReader(流);
用于(长i=0;i<(长度);i++)
{
source.Add(reader.ReadByte());//在i=134217728处给出异常
}
reader.Dispose();
reader.Close();
stream.Dispose();
stream.Close();
}

看起来您正在使用一个
列表。这将是一种非常低效的复制数据的方法,而且使用多个线程可能会降低复制数据的效率。此外,如果您使用的是来自多个线程的单个列表,则代码已经被破坏-
list
不是线程安全的。即使是这样,您也会混合来自不同线程的数据,因此无法重新组合原始数据。哦,如果不使用
语句,那么如果抛出异常,您将使文件句柄保持打开状态。换句话说,我建议你完全放弃目前的方法

相反,将文件从一个地方复制到另一个地方(假设您因某种原因无法使用),基本上应该是:

  • 打开流进行读取
  • 打开要写入的流
  • 分配缓冲区(例如32K)
  • 反复:
    • 从“输入”流读入缓冲区,注意调用实际读取的数据量
    • 将刚刚读取的数据写入输出流
    • 循环,直到“读取”指示输入流的结束
  • 关闭两个流(使用
    语句)

没有必要把一切都记在记忆里。请注意,在.NET4中,使用该方法更容易实现这一点。第三步和第四步哪一步适合您。

有什么例外?不使用
语句的任何原因?一般来说,在一个磁盘上使用多个线程进行IO是一个坏主意——你只是在强迫它进行重击。您在这里可以实现的最大性能改进很可能是一次读取数据块,而不是大量调用
ReadByte
。啊,我现在看到您有一个
OutOfMemoryException
。源代码的类型是什么?(我希望你不是同时从多个线程中使用一个简单的
列表
。)是的,我使用列表,我不知道我有没有其他方法,我使用了byte[],但它并没有我想要的那么大查看我的答案-之后你到底在用列表做什么?真的吗?列表中有3GB?但当我使用流读取并复制到其他位置时,其他线程将无法使用文件复制其他部分,该怎么办?@Cavidanquily耶夫:正如我所解释的,无论如何,你不应该使用多个线程复制单个文件-这只会导致磁盘抖动。您是否尝试过简单的方法,但发现它太慢了?您可能会使用异步IO,并在写入输出的同时读取输入,但我个人不会这样做,直到我证明上述方法太慢。