winforms 通过网络读取文件非常慢

pkwftd7m  于 2023-06-24  发布在  其他
关注(0)|答案(3)|浏览(133)

我在阅读网络驱动器上的大文件(~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);
}
zte4gxcn

zte4gxcn1#

我迟到了,但最近也遇到了同样的网络利用率低的问题,在尝试了很多不同的实现之后,如果最后发现一个带有大缓冲区(在我的情况下是1MB)的StreamReader将网络利用率提高到了99%。其他选项均未产生重大变化。

7gs2gvoe

7gs2gvoe2#

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

piv4azn7

piv4azn73#

使用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
不确定这会有帮助,但很容易尝试。

相关问题