In my WPF application the data that UI displays will be updated too frequently. I figured out that it will be great to leave the logic intact and solve this issue with an extra class that stores the most recent data and raises the update event after some delay.
So the goal is to update UI, lets say every 50 ms, and display the most recent data. But if there is no new data to show, then the UI shan't be updated.
Here is an implementation I have created so far. Is there a way to do it without locking? Is my implementation correct?
class Publisher<T>
{
private readonly TimeSpan delay;
private readonly CancellationToken cancellationToken;
private readonly Task cancellationTask;
private T data;
private bool published = true;
private readonly object publishLock = new object();
private async void PublishMethod()
{
await Task.WhenAny(Task.Delay(this.delay), this.cancellationTask);
this.cancellationToken.ThrowIfCancellationRequested();
T dataToPublish;
lock (this.publishLock)
{
this.published = true;
dataToPublish = this.data;
}
this.NewDataAvailable(dataToPublish);
}
internal Publisher(TimeSpan delay, CancellationToken cancellationToken)
{
this.delay = delay;
this.cancellationToken = cancellationToken;
var tcs = new TaskCompletionSource<bool>();
cancellationToken.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: false);
this.cancellationTask = tcs.Task;
}
internal void Publish(T data)
{
var runNewTask = false;
lock (this.publishLock)
{
this.data = data;
if (this.published)
{
this.published = false;
runNewTask = true;
}
}
if (runNewTask)
Task.Run((Action)this.PublishMethod);
}
internal event Action<T> NewDataAvailable = delegate { };
}