在C#中避免BinaryReader.ReadString()?

在C#中避免BinaryReader.ReadString()?,c#,C#,早上好 在我编写的应用程序启动时,我需要从一个文件中读取大约1600000个条目到字典中。使用BinaryReader构建整个结构大约需要4-5秒(使用FileReader大约需要相同的时间)。我分析了代码,发现在这个过程中做最多工作的函数是BinaryReader.ReadString()。虽然这个过程只需要在启动时运行一次,但我希望它尽可能快。有什么方法可以避免BinaryReader.ReadString()并加快此过程 非常感谢。您确定在继续之前一定要这样做吗 我将研究是否有可能将任务分

早上好

在我编写的应用程序启动时,我需要从一个文件中读取大约1600000个条目到
字典中。使用BinaryReader构建整个结构大约需要4-5秒(使用FileReader大约需要相同的时间)。我分析了代码,发现在这个过程中做最多工作的函数是
BinaryReader.ReadString()
。虽然这个过程只需要在启动时运行一次,但我希望它尽可能快。有什么方法可以避免BinaryReader.ReadString()
并加快此过程

非常感谢。

您确定在继续之前一定要这样做吗

我将研究是否有可能将任务分离到一个单独的线程,该线程在完成时设置一个标志。然后,您的启动代码简单地启动该线程并继续其愉快的方式,仅在以下两种情况下暂停:

  • 旗帜还没有升起;及
  • 没有这些数据,就不能再做更多的工作了
通常,速度的幻觉已经足够好了,任何一个编写了启动屏幕的人都会告诉你

如果你控制数据,另一种可能性是以更二进制的形式存储数据,这样你只需点击一下就可以将数据全部写入(即,不解释数据,只读取整个数据)。当然,这使得从应用程序外部编辑数据变得更加困难,但您还没有将此作为一项要求

如果这是一项要求,或者您不控制数据,我仍然会研究我上面的第一个建议。

您确定在继续之前必须这样做吗

我将研究是否有可能将任务分离到一个单独的线程,该线程在完成时设置一个标志。然后,您的启动代码简单地启动该线程并继续其愉快的方式,仅在以下两种情况下暂停:

  • 旗帜还没有升起;及
  • 没有这些数据,就不能再做更多的工作了
通常,速度的幻觉已经足够好了,任何一个编写了启动屏幕的人都会告诉你

如果你控制数据,另一种可能性是以更二进制的形式存储数据,这样你只需点击一下就可以将数据全部写入(即,不解释数据,只读取整个数据)。当然,这使得从应用程序外部编辑数据变得更加困难,但您还没有将此作为一项要求


如果这是一个要求,或者您不控制数据,我仍然会研究我上面的第一个建议。

如果字符串在元组中重复,您可以重新组织文件,在开始时包含所有不同的涉及字符串,并在文件体中引用这些字符串(整数)。您的主字典不必更改,但在启动过程中需要一个临时字典,其中包含所有不同的字符串(值)及其引用(键)。

如果字符串在元组中重复,您可以重新组织文件,使其在开始时包含所有不同的涉及字符串,并引用这些字符串(整数)在文件的正文中。您的主词典不必更改,但在启动过程中需要一个临时词典,其中包含所有不同的字符串(值)及其引用(键)。

如果您认为逐行读取文件是瓶颈,并且取决于文件的大小,您可以尝试一次读取所有文件:

// read the entire file at once
string entireFile = System.IO.File.ReadAllText(path);
如果这没有帮助,您可以尝试添加一个带有信号量的单独线程,该线程将在程序启动时立即在后台开始读取,但在您尝试访问数据时阻止请求线程

这称为未来,在Jon Skeet的库中有一个实现

在应用程序启动时,您可以这样称呼它:

// following line invokes "DoTheActualWork" method on a background thread.
// DoTheActualWork returns an instance of MyData when it's done
Future<MyData> calculation = new Future<MyData>(() => DoTheActualWork(path));
如果查看Future的Value属性,可以看到,如果线程仍在运行,它会在AsyncWaitHandle处阻塞:

public TResult Value
{
    get
    {
        if (!IsCompleted)
        {
            _asyncResult.AsyncWaitHandle.WaitOne();
            _lock.WaitOne();
        }
        return _value;
    }
}

如果您认为逐行读取文件是瓶颈,取决于文件大小,您可以尝试一次读取所有文件:

// read the entire file at once
string entireFile = System.IO.File.ReadAllText(path);
如果这没有帮助,您可以尝试添加一个带有信号量的单独线程,该线程将在程序启动时立即在后台开始读取,但在您尝试访问数据时阻止请求线程

这称为未来,在Jon Skeet的库中有一个实现

在应用程序启动时,您可以这样称呼它:

// following line invokes "DoTheActualWork" method on a background thread.
// DoTheActualWork returns an instance of MyData when it's done
Future<MyData> calculation = new Future<MyData>(() => DoTheActualWork(path));
如果查看Future的Value属性,可以看到,如果线程仍在运行,它会在AsyncWaitHandle处阻塞:

public TResult Value
{
    get
    {
        if (!IsCompleted)
        {
            _asyncResult.AsyncWaitHandle.WaitOne();
            _lock.WaitOne();
        }
        return _value;
    }
}

+我讨厌冷启动应用程序。只有在绝对必要的时候才请求数据,或者在一些后台任务中请求数据…+1,我讨厌冷启动应用程序。只有在绝对必要时才请求数据,或者在某些后台组任务中请求数据……除非您确实需要它来读取未对齐的位/数据,否则不要同时使用
binarydreader
。除非您确实需要它来读取未对齐的位/数据,否则不要同时使用
binarydreader