Mudassir Ansari
Mudassir Ansari

Reputation: 1

WPF Event Aggregator - wait for previous execution to complete

I am working on a WPF application using Prism. I am using EventAggregator to communicate between viewmodels.

public class PublisherViewModel
{
   _eventAggregator.GetEvent<RefreshEvent>().Publish("STOCKS");
}
public class SubscriberViewModel
{
    public SubscriberViewModel(IEventAggregator ea)
    {
        ea.GetEvent<RefreshEvent>().Subscribe(RefreshData);
    }

    void RefreshData(string category)
    {
        Task.Run(() =>
        {
                //Long Running Operation

                Dispatcher.Invoke(() =>
                {
                     //Refresh UI
                });
        });
    }
}

PublisherViewModel can publish event one after another. However at a SubscriberViewModel as I have a long running Task and is not awaited (which I cannot) the second request coming from publisher start execution right away. At SubscriberViewModel I want to handle all incoming request such that they are executed one after another in the order which they arrive.

I am thinking to handle this using a queue based mechanism.

Could you please suggest me the best practice for the same.

Thanks!!

Update:- I have used the below approach

public class BlockingQueue<T> wehre T : class
{
    private readonly BlockingCollection<JobQueueItem<T>> _jobs;
    public BlockingQueue(int upperBound)
    {
        _jobs = new BlockingCollection<JobQueueItem<T>>(upperBound);
        var thread = new Thread(new ThreadStart(OnStart));
        thread.IsBackground = true;
        thread.Start();
    }

    public void Enqueue(T parameter, Func<T, Task> action)
    {
        _jobs.Add(new JobQueueItem<T> { Parameter = parameter, JobAction = action });
    }

    private void OnStart()
    {
        foreach (var job in _jobs.GetConsumingEnumerable(CancellationToken.None))
        {
            if (job != null && job.JobAction != null)
            {
                job.Action.Invoke(job.Parameter).Wait();
            }
        }
    }

    private class JobQueueItem<T>
    {
        internal T Parameter { get; set; }
        internal Func<T, Task> JobAction { get; set; }
    }
}
public class SubscriberViewModel
{
    BlockingQueue<RefreshEventArgs> RefreshQueue = new ...;

    //inside Subscribed method
    RefreshQueue.Enqueue(args, RefreshData);
}

Please suggest. Thanks!

Upvotes: 0

Views: 927

Answers (1)

Haukinger
Haukinger

Reputation: 10863

I am thinking to handle this using a queue based mechanism.

This is the way to go. Set up a queue (probably an asynchronous queue), push the events in the subscriber and consume them from a worker task.

TPL Dataflow is one option to do this: create an ActionBlock<string> from the handler and post the events to it as they come in.

Upvotes: 0

Related Questions