Я работаю над приложением для отображения данных журнала andorid в режиме реального времени, каждый раз, когда я подключаю устройство для отображения журнала, сначала будут отображаться данные журнала в кеше, около 100 000 строк журнала. Когда я отображал журнал, я использовал привязку данных, но это было не так быстро, как я думал, мне потребовалось более 1 минуты, чтобы отобразить около 100 000 строк журнала на сетке данных, и пока он отображал данные, вертикальная полоса прокрутки очень медленная и запаздывает. Горизонтальная полоса прокрутки такая же, и моя таблица состоит из 7 столбцов. Пожалуйста, помогите мне улучшить описанную выше ситуацию. Есть ли другой способ ускорить отображение данных и повысить производительность полос прокрутки? Вот мой код:
MainWindow_LogViewDataGrid.xaml
<UserControl x:Class="SmartLogAnalyze.MVVM.UserControls.MainWindow_LogViewDataGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SmartLogAnalyze.MVVM.UserControls"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<DataGrid AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" IsReadOnly="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" ItemsSource="{Binding LogItemVMs, IsAsync=True}"
x:Name="datagrid" EnableColumnVirtualization="True" EnableRowVirtualization ="True"
VirtualizingStackPanel.IsVirtualizing ="True" VirtualizingStackPanel.VirtualizationMode="Recycling"
VirtualizingPanel.ScrollUnit="Pixel" GridLinesVisibility="None" Margin="0,3,2,5">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Line" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Line,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Date" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Date,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Time" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Time,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="LogLV" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Level,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Pid" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Pid,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Tid" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Tid,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Tag" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Tag,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Message" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Message,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
И это класс для добавления данных в таблицу и отображения: RunFeaturenAction.cs
class RunFeatureAction : IAction
{
private static string _device = "";
private static string _command = "";
private static MainWindowVM _model;
private static Process _proc;
private StateController _stateController = StateController.Instance;
private ComboBox _cbxCommand;
private ListBox _listbxDevice;
private Thread _parsingThread = new Thread(() =>
{
string line = "abc";
try
{
_proc.Start();
//Parsing log and add it to datagrid here
while ((line = _proc.StandardOutput.ReadLine()) != null)
{
LogInfo lif = LogInfoManager.Instance.ParseLogInfos(line, _model.LogCount);
if (lif != null)
{
LogItemVM livm = new LogItemVM(lif);
App.Current.Dispatcher.Invoke(()=>
{
_model.LogItemVMs.Add(livm);
_model.LogCount++;
});
}
StateController.Instance.PausingEvent.WaitOne();
if (StateController.Instance.StopEvent.WaitOne(0))
break;
}
_proc.WaitForExit();
}
catch
{
}
finally
{
if (!_proc.HasExited)
_proc.Kill();
}
});
public bool Execute(object[] dataTransfer)
{
_model = (MainWindowVM)dataTransfer[0];
var items = (object[])dataTransfer[1];
_cbxCommand = (ComboBox)items[0];
_listbxDevice = (ListBox)items[1];
if (!IsNeedToUpdateRunningState())
{
MessageBoxUtil.ShowWarning("Choose device and run again.");
return false;
}
else if (_model.LstDevice.Count == 1)
{
_device = _model.LstDevice[0].getSerialNumber();
_command = _cbxCommand.Text;
}
else
{
_device = _model.LstDevice[_listbxDevice.SelectedIndex].getSerialNumber();
_command = _cbxCommand.Text;
}
StateController.Instance.UpdateRunningState();
CheckNeedToResetLogCount();
return true;
}
private bool IsNeedToUpdateRunningState()
{
return !((_listbxDevice.SelectedIndex == -1 && _model.LstDevice.Count > 1)
|| _model.LstDevice.Count == 0);
}
private void CreateProcces()
{
if (!_device.Equals("") && !_command.Equals(""))
_proc = CommandImpl.Instance.CreateProcess(" -s " + _device + " " + _command);
else
_proc = CommandImpl.Instance.CreateProcess(" logcat");
}
private void CheckNeedToResetLogCount()
{
if (_model == null)
{
return;
}
if (_stateController.PreState == StateLevel.NONE || _stateController.PreState == StateLevel.STOP)
{
StateController.Instance.Start();
CreateProcces();
_model.LogCount = 0;
_model.LogItemVMs.Clear();
_model.IsRunning = true;
_parsingThread.Start();
}
else if (_stateController.PreState == StateLevel.PAUSING)
{
StateController.Instance.Resume();
_model.IsRunning = true;
}
}
}