通过网络读取文件非常慢

时间:2012-05-31 15:56:03

标签: c# .net winforms file-io network-programming

我在读取网络驱动器上的大文件(~400 mb)时遇到了一个有趣的问题。或者,我将完整的网络地址输入FileInfo并使用CopyTo函数将其传输到本地临时驱动器然后读取它。这似乎工作正常,它不慢但它不快 - 只是meh。 CopyTo函数可以使计算机运行程序的网络利用率一直高于50%,这是非常好的。

为了加快这个过程,我尝试将网络文件直接读入内存流,以便切断中间人。当我尝试这个(使用描述here的异步复制模式)时,它非常慢。我的网络利用率甚至从未超过2% - 它几乎就像限制了我一样。仅供参考,我通过Windows资源管理器直接复制相同的文件时看到了我的网络利用率,它达到了80-90%...不确定这里发生了什么。下面是我使用的异步复制代码:

string line;
List<string> results = new List<string>();

Parser parser = new Parser(QuerySettings.SelectedFilters, QuerySettings.SearchTerms,
QuerySettings.ExcludedTerms, QuerySettings.HighlightedTerms);

byte[] ActiveBuffer = new byte[60 * 1024];
byte[] BackBuffer = new byte[60 * 1024];
byte[] WriteBuffer = new byte[60 * 1024];

MemoryStream memStream = new MemoryStream();
FileStream fileStream = new FileStream(fullPath, FileMode.Open, FileSystemRights.Read, FileShare.None, 60 * 1024, FileOptions.SequentialScan);

int Readed = 0;
IAsyncResult ReadResult;
IAsyncResult WriteResult;

ReadResult = fileStream.BeginRead(ActiveBuffer, 0, ActiveBuffer.Length, null, null);
do
{
    Readed = fileStream.EndRead(ReadResult);

    WriteResult = memStream.BeginWrite(ActiveBuffer, 0, Readed, null, null);
    WriteBuffer = ActiveBuffer;

    if (Readed > 0)
    {
        ReadResult = fileStream.BeginRead(BackBuffer, 0, BackBuffer.Length, null, null);
        BackBuffer = Interlocked.Exchange(ref ActiveBuffer, BackBuffer);
    }

    memStream.EndWrite(WriteResult);
}
while (Readed > 0);

StreamReader streamReader = new StreamReader(memStream);
while ((line = streamReader.ReadLine()) != null)
{
    if (parser.ParseResults(line))
    results.Add(line);
}

fileStream.Flush();
fileStream.Close();

memStream.Flush();
memStream.Close();

return results;

更新 根据评论我刚刚尝试了以下内容。它的网络利用率只有10-15%......为什么这么低?

MemoryStream memStream = new MemoryStream();
FileStream fileStream = File.OpenRead(fullPath);

fileStream.CopyTo(memStream);

memStream.Seek(0, 0);
StreamReader streamReader = new StreamReader(memStream);

Parser parser = new Parser(QuerySettings.SelectedFilters, QuerySettings.SearchTerms,
QuerySettings.ExcludedTerms, QuerySettings.HighlightedTerms);

while ((line = streamReader.ReadLine()) != null)
{
if (parser.ParseResults(line))
results.Add(line);
}

3 个答案:

答案 0 :(得分:3)

我迟到了,但最近遇到了同样的网络利用率低的问题,在尝试了很多不同的实现后,如果最后发现一个带有大缓冲区的StreamReader(在我的情况下为1MB)增加了网络利用率达到99%。 没有其他选择确实做出了重大改变。

答案 1 :(得分:1)

没有必要复制整个文件然后解析它。只需从网络驱动器打开文件,让.Net Framework尽力为您提供数据。你可以比MS开发人员更聪明,你可以比他们更快地创建一个复制方法,但这确实是一个挑战。

答案 2 :(得分:1)

使用Reflector,我看到您的呼叫:

FileStream fileStream = File.OpenRead(fullPath);

最终使用大小为4096字节(0x1000)的缓冲区。

public FileStream(string path, FileMode mode, FileAccess access, FileShare share) : this(path, mode, access, share, 0x1000, FileOptions.None, Path.GetFileName(path), false)
{
}

您可以尝试显式调用其中一个 FileStream 构造函数,并指定更大的缓冲区大小和 FileOption.SequentialScan

不确定这会有所帮助,但很容易尝试。