using Quasar.Common.Networking; using System; using System.Threading; namespace Quasar.Common.Messages { /// /// Provides a MessageProcessor implementation that provides progress report callbacks. /// /// Specifies the type of the progress report value. /// /// Any event handlers registered with the event are invoked through a /// instance chosen when the instance is constructed. /// public abstract class MessageProcessorBase : IMessageProcessor, IProgress { /// /// The synchronization context chosen upon construction. /// protected readonly SynchronizationContext SynchronizationContext; /// /// A cached delegate used to post invocation to the synchronization context. /// private readonly SendOrPostCallback _invokeReportProgressHandlers; /// /// Represents the method that will handle progress updates. /// /// The message processor which updated the progress. /// The new progress. public delegate void ReportProgressEventHandler(object sender, T value); /// /// Raised for each reported progress value. /// /// /// Handlers registered with this event will be invoked on the /// chosen when the instance was constructed. /// public event ReportProgressEventHandler ProgressChanged; /// /// Reports a progress change. /// /// The value of the updated progress. protected virtual void OnReport(T value) { // If there's no handler, don't bother going through the sync context. // Inside the callback, we'll need to check again, in case // an event handler is removed between now and then. var handler = ProgressChanged; if (handler != null) { SynchronizationContext.Post(_invokeReportProgressHandlers, value); } } /// /// Initializes the /// /// /// If this value is false, the progress callbacks will be invoked on the ThreadPool. /// Otherwise the current SynchronizationContext will be used. /// protected MessageProcessorBase(bool useCurrentContext) { _invokeReportProgressHandlers = InvokeReportProgressHandlers; SynchronizationContext = useCurrentContext ? SynchronizationContext.Current : ProgressStatics.DefaultContext; } /// /// Invokes the progress event callbacks. /// /// The progress value. private void InvokeReportProgressHandlers(object state) { var handler = ProgressChanged; handler?.Invoke(this, (T)state); } /// public abstract bool CanExecute(IMessage message); /// public abstract bool CanExecuteFrom(ISender sender); /// public abstract void Execute(ISender sender, IMessage message); void IProgress.Report(T value) => OnReport(value); } /// /// Holds static values for . /// /// /// This avoids one static instance per type T. /// internal static class ProgressStatics { /// /// A default synchronization context that targets the . /// internal static readonly SynchronizationContext DefaultContext = new SynchronizationContext(); } }