1

我有一个程序可以显示日志文件中的行。

它们被解析并放入一个名为 LogLine 的类中,然后显示在数据网格中

这是我的过滤功能:

ICollectionView view = CollectionViewSource.GetDefaultView(this.LogView.ItemsSource);
bool traceChecked = this.TraceCheckbox.IsChecked.HasValue &&     this.TraceCheckbox.IsChecked.Value;
bool debugChecked = this.DebugCheckbox.IsChecked.HasValue && this.DebugCheckbox.IsChecked.Value;
bool infoChecked = this.InfoCheckbox.IsChecked.HasValue && this.InfoCheckbox.IsChecked.Value;
bool warnChecked = this.WarnCheckbox.IsChecked.HasValue && this.WarnCheckbox.IsChecked.Value;
bool errorChecked = this.ErrorCheckbox.IsChecked.HasValue && this.ErrorCheckbox.IsChecked.Value;
string filtertext = this.TextFilterBox.Text;
view.Filter = o =>
    {
        LogLine line = o as LogLine;
        return line != null
               && (((traceChecked && line.Trace) 
               || (debugChecked && line.Debug) 
               || (infoChecked && line.Info) 
               || (warnChecked && line.Warn) 
               || (errorChecked && line.Error))
               && line.Message.Contains(filtertext));
    };

这个函数已经很慢了,在一个有 200000 行的日志上需要将近 5 秒。

可以做些什么来加快这个速度?

根据 HighCore 的建议,我实现了一个真正的 ViewModel。这稍微快了一点,但仍然需要 5-6 秒才能扔掉 ObservableCollection 的所有行

ICollectionView view = CollectionViewSource.GetDefaultView(this.LogView.ItemsSource);
LogViewModel lvm = (LogViewModel)this.DataContext;
view.Filter = o =>
    {
        LogLine line = o as LogLine;
        if (line == null || !line.Message.Contains(lvm.FilterText))
            {
                return false;
            }

            switch (line.LogLevel)
            {
                case LogViewModel.LogLevel.Trace:
                    return lvm.Trace;
                case LogViewModel.LogLevel.Debug:
                    return lvm.Debug;
                case LogViewModel.LogLevel.Info:
                    return lvm.Info;
                case LogViewModel.LogLevel.Warn:
                    return lvm.Warn;
                case LogViewModel.LogLevel.Error:
                    return lvm.Error;
                default:
                    return false;
            }
        };
4

1 回答 1

1

我写了一个类似的日志查看器应用程序,但使用了不同的方法。

我对您的 LogLine 之类的类执行初始解析并将它们存储在列表中。然后当用户选择各种过滤器组合时,我使用 Linq 构建一个 IEnumerable 过滤器匹配项,该过滤器匹配项绑定到项目控件(在我的情况下为 ListView)。如果您愿意,可以使用 ObservableCollection 并清除/填充相同的结果。

我刚刚测试了一个 31MB 的文件(240k 行),结果在更改过滤器时会在一秒钟内显示出来。

于 2013-02-26T14:43:04.133 回答