Reputation: 83
I am using Websockets to draw data on my canvas:
webSocket.OnMessage += (sender, e) =>
{
String websocketData = e.Data.Substring(3);
WebSocketDataStructure jsonData = JsonConvert.DeserializeObject<WebSocketDataStructure>(websocketData);
// Give control back to main thread for drawing
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => this.updateCanvas(jsonData)));
};
private void updateCanvas(WebSocketDataStructure myData)
{
CanvasUtils.DrawLine(MyCanvas, colorNormalBrush, myData.hsLine.x1, myData.hsLine.y1, myData.hsLine.x2, myData.hsLine.y2);
}
When I get multiple messages per second the application starts to lag. I read that using Dispatcher.BeginInvoke() is bad for handling frequent data, since we immediately switch back to the UI-Thread every time.
Is there a better way to implement this? I thought about creating a timer and updating the UI-Thread every full second. This would work by storing websocket data in a List, and process it on the UI-Thread (https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem). My only problem with this approach was, that I couldn't set up an endless loop with Thread.Sleep(1000) on the UI-Thread.
Upvotes: 2
Views: 1074
Reputation: 1049
You could queue your high-frequent data and read items from the data queue at a lower pace. By using a DispatcherTimer you could avoid the need for directly calling the Dispatcher.
var queue = new ConcurrentQueue<WebSocketDataStructure>();
webSocket.OnMessage += (s, e) =>
{
var websocketData = e.Data.Substring(3);
var jsonData = JsonConvert.DeserializeObject<WebSocketDataStructure>(websocketData);
queue.Enqueue(jsonData);
};
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
timer.Tick += (s, e) =>
{
WebSocketDataStructure data;
while (queue.TryDequeue(out data))
{
CanvasUtils.DrawLine(MyCanvas, colorNormalBrush,
data.hsLine.x1, data.hsLine.y1, data.hsLine.x2, data.hsLine.y2);
}
};
timer.Start();
Upvotes: 2