안녕하세요.
제가 최근에 관심있는 주제가 있어서 이렇게 글을 올립니다.
라이다 데이터를 이용해서 WPF Canvas에 표현을 하려고 하는데요.
약 7Hz로 회전하는 라이다가 있습니다.
약 150 ms 당 3800개의 포인트를 리스트를 만들어서 Canvas에 뿌려줍니다.
고속의 데이터를 실시간으로 보여주려고 하는데요.
아래는 제가 표현하려고하는 방식입니다.
그런데 Canvas에 아래 코드로 실행하면 프로그램이 멈출정도로 느려지는 현상이 있습니다.
그러다가 프로그램이 죽는데, 3~4천개면 엄청 대량의 데이터도 아니고, WPF가 느린건지 아니면
구현 방법이 잘못된건지 모르겠습니다. 물론 제 구현방법이 잘못된것이라고 생각되지만, WPF가 참
이럴때마다 좀실망스럽네요. ㅠㅠ
<UserControl.Resources>
<utils:OffsetConverter x:Key="OffsetConverter"/>
</UserControl.Resources>
<Canvas Background="#88000000"
ClipToBounds="True">
<ItemsControl ItemsSource="{Binding Points, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="3" Height="3" Fill="WhiteSmoke">
<Ellipse.RenderTransform>
<!--<TranslateTransform X="{Binding X, Converter={StaticResource OffsetConverter}, ConverterParameter=X}" Y="{Binding Y, Converter={StaticResource OffsetConverter}, ConverterParameter=Y}"/>-->
<TranslateTransform X="{Binding X}" Y="{Binding Y}"/>
</Ellipse.RenderTransform>
</Ellipse>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<!--<Setter Property="Canvas.Left" Value="{Binding X, Converter={StaticResource OffsetConverter}, ConverterParameter=X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y, Converter={StaticResource OffsetConverter}, ConverterParameter=Y/> -->
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Canvas>
이렇게 표현하고,
ViewModel은 이렇게 사용합니다.
public class VisualViewModel : BaseViewModel
{
#region - Ctors -
public VisualViewModel(IEventAggregator eventAggregator
, LidarService lidarService)
: base(eventAggregator)
{
_lidarService = lidarService;
locker = new object();
}
#endregion
#region - Implementation of Interface -
#endregion
#region - Overrides -
protected override Task OnActivateAsync(CancellationToken cancellationToken)
{
_lidarService.SendPoints += _lidarService_SendPoints;
return base.OnActivateAsync(cancellationToken);
}
protected override Task OnDeactivateAsync(bool close, CancellationToken cancellationToken)
{
return base.OnDeactivateAsync(close, cancellationToken);
}
#endregion
#region - Binding Methods -
#endregion
#region - Processes -
private Task _lidarService_SendPoints(List<Measure> measures)
{
return Task.Run(() =>
{
Application.Current.Dispatcher.Invoke(() =>
{
Points = measures;
NotifyOfPropertyChange(() => Points);
});
});
//return Task.Run(() =>
//{
// lock (locker)
// {
// Debug.WriteLine($"=====Start=====");
// foreach (var item in measures)
// {
// Debug.WriteLine($"θ:{item.angle}, L:{item.distance}, X:{item.X}, Y:{item.Y}");
// }
// Debug.WriteLine($"=====End=====");
// }
//});
}
#endregion
#region - IHanldes -
#endregion
#region - Properties -
public List<Measure> Points { get; set; }
#endregion
#region - Attributes -
private LidarService _lidarService;
private object locker;
#endregion
}
어떻게 접근하는 것이 좋을지 조언 부탁드립니다.