// at least once delivery check async Task AtLeastOnceDeliveryExample() { var hub = new MetaPubSub(); var message = new MyMessage { // if this not set, NoSubscribersException will not be thrown DeliverAtLeastOnce = true }; try { // publishing a message when no one is subscribed await hub.Publish(message); } catch (NoSubscribersException ex) { // no one is listening Console.WriteLine($"Exception {ex.GetType()}: {ex.Message}"); } hub.Subscribe <MyMessage>(OnMyMessage); await hub.Publish(message); await hub.Unsubscribe <MyMessage>(OnMyMessage); }
public void SetDevice(IDevice device) { _device = device; _device.ConnectionStateChanged += (object sender, EventArgs e) => { try { if (!IsConnected && CurrentState == State.Wiping) { CurrentState = State.Success; _hub.Publish(new DeviceWipedEvent(this)); } NotifyPropertyChanged(nameof(IsConnected)); } catch (Exception ex) { MessageBox.Show(ex.Message); } }; _device.PropertyChanged += (object sender, string e) => { NotifyPropertyChanged(e); }; NotifyPropertyChanged(nameof(SerialNo)); }
void ConnectionManager_AdvertismentReceived(object sender, AdvertismentReceivedEventArgs e) { if (e.Rssi > SdkConfig.TapProximityUnlockThreshold) { _hub.Publish(new AdvertismentReceivedEvent(e)); } }
// subscribed twice but delivered only once public async Task Basic() { var hub = new MetaPubSub(); await Task.Run(() => { for (int i = 0; i < 10_000; i++) { var subscriber = new MySubscriber(); //await Task.Delay(50); hub.Subscribe <MyMessage>(subscriber.Handler); } }); int totalDeliveryCount1 = 0; var t1 = Task.Run(async() => { for (int i = 0; i < 1000; i++) { var subscriber = new MySubscriber(); hub.Subscribe <MyEvent>(subscriber.Handler); var message = new MyMessage(); await hub.Publish(message); totalDeliveryCount1 += message.DeliveredCount; await hub.Unsubscribe <MyEvent>(subscriber.Handler); } }); int totalDeliveryCount2 = 0; var t2 = Task.Run(async() => { for (int i = 0; i < 1000; i++) { var subscriber = new MySubscriber(); hub.Subscribe <MyMessage>(subscriber.Handler); var message = new MyMessage(); await hub.Publish(message); totalDeliveryCount2 += message.DeliveredCount; await hub.Unsubscribe <MyMessage>(subscriber.Handler); } }); await Task.WhenAll(t1, t2); Assert.IsTrue(totalDeliveryCount1 > (10_000 * 1000) && totalDeliveryCount1 < (10_000 * 1000 + 1000)); Assert.IsTrue(totalDeliveryCount2 == 10_000 * 1000 + 1000); }
// same as previous but should not deliver the message // because the second subscriber has also the same filter public async Task Test_DeliverAtLeastOnce_Delayed2() { var hub = new MetaPubSub(); bool timeoutException = false; // first subscriber which will not process the message due to its filter hub.Subscribe <MyMessage>(OnMyMessageHandler, OnMyMessagePredicate); // second subscriber which will subscribe after the message has been published var t = Task.Run(async() => { await Task.Delay(50); hub.Subscribe <MyMessage>(OnMyMessageHandler2, OnMyMessagePredicate); await hub.Unsubscribe <MyMessage>(OnMyMessageHandler2); }); var message = new MyMessage { LogSeverity = MetaLogErrorSeverity.Info, DeliverAtLeastOnce = true, WaitForSubscriberTimeout = 100 }; try { // the message has a timeout and can wait until the second subscriber come await hub.Publish(message); } catch (TimeoutException) { timeoutException = true; } Assert.IsTrue(timeoutException); Assert.IsTrue(message.DeliveredCount == 0); await hub.Unsubscribe <MyMessage>(OnMyMessageHandler); }
// cancellation token support - you can cancel scheduling or waiting for the message public static async Task CancellationExample() { var hub = new MetaPubSub(); var cts = new CancellationTokenSource(); // publish an event after 100 ms var t = Task.Run(async() => { await Task.Delay(100); await hub.Publish(new MyEvent()); }); // cancel waiting after 50 ms var t2 = Task.Run(async() => { await Task.Delay(50); cts.Cancel(); }); try { var res = await hub.When <MyEvent>(millisecondsTimeout : 200, match : null, cts.Token); } catch (OperationCanceledException) { Console.WriteLine("Waiting for MyEvent has been canceled"); } }
public async Task Test_When() { var hub = new MetaPubSub(); var t = Task.Run(async() => { await Task.Delay(50); await hub.Publish(new MyEvent()); }); var res = await hub.When <MyEvent>(100); Assert.IsNotNull(res); bool timeoutException = false; try { res = await hub.When <MyEvent>(100); } catch (TimeoutException) { timeoutException = true; } Assert.IsTrue(timeoutException); }
public async Task Test_Cancel_When() { var hub = new MetaPubSub(); var cts = new CancellationTokenSource(); // publish an event after 100 ms var t = Task.Run(async() => { await Task.Delay(100); await hub.Publish(new MyEvent()); }); // cancel waiting after 50 ms var t2 = Task.Run(async() => { await Task.Delay(50); cts.Cancel(); }); bool exception = false; try { var res = await hub.When <MyEvent>(200, null, cts.Token); Assert.IsTrue(false); } catch (OperationCanceledException) { exception = true; } Assert.IsTrue(exception); }
// timeout to wait for a subscriber - your message can be queued and wait until someone subscribed and processed it public async Task DeliverAtLeastOnceDelayedExample() { var hub = new MetaPubSub(); // a subscriber that will subscribe after the message has been published var t = Task.Run(async() => { await Task.Delay(1500); Console.WriteLine($"Subscribed to MyMessage at {DateTime.Now:HH:mm:ss.fff}"); hub.Subscribe <MyMessage>(OnMyMessage); }); // the message has the 10 seconds timeout and can wait until the subscriber come var message = new MyMessage { DeliverAtLeastOnce = true, // this must be set to true WaitForSubscriberTimeout = 10_000 }; Console.WriteLine($"Start publishing and awaiting at {DateTime.Now:HH:mm:ss.fff}"); // this method will wait until the subscriber receives the message or until timeout expired (10 seconds) await hub.Publish(message); Console.WriteLine($"End awaiting at {DateTime.Now:HH:mm:ss.fff}"); await hub.Unsubscribe <MyMessage>(OnMyMessage); }
protected override async void OnClosing(CancelEventArgs e) { var vm = (MainWindowViewModel)DataContext; if (vm.IsFirmwareUpdateInProgress) { var mb = MessageBox.Show( "Firmware update in progress!" + Environment.NewLine + "Are you sure you want to exit?", "Exit application", MessageBoxButton.YesNoCancel, MessageBoxImage.Exclamation); if (mb != MessageBoxResult.Yes) { e.Cancel = true; return; } } try { await _hub.Publish(new ClosingEvent()); base.OnClosing(e); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); e.Cancel = true; } }
// Should deliver if message is filtered at first and DeliverAtLeastOnce = true but Timeout > 0 and // after the message has published a new subscriber arrived public async Task Test_DeliverAtLeastOnce_Delayed() { var hub = new MetaPubSub(); // first subscriber which will not process the message due to its filter hub.Subscribe <MyMessage>(OnMyMessageHandler, OnMyMessagePredicate); // second subscriber which will subscribe after the message has been published // also with filter, will not process the message var t = Task.Run(async() => { await Task.Delay(50); hub.Subscribe <MyMessage>(OnMyMessageHandler2, OnMyMessagePredicate); }); // third subscriber which will subscribe after the message has been published var t2 = Task.Run(async() => { await Task.Delay(70); hub.Subscribe <MyMessage>(OnMyMessageHandler3); }); var message = new MyMessage { LogSeverity = MetaLogErrorSeverity.Info, DeliverAtLeastOnce = true, WaitForSubscriberTimeout = 200000 }; // the message has a timeout and can wait until the second subscriber come await hub.Publish(message); Assert.IsTrue(message.DeliveredCount == 1); await hub.Unsubscribe <MyMessage>(OnMyMessageHandler); //hub.Unsubscribe<MyMessage>(OnMyMessageHandler2); //hub.Unsubscribe<MyMessage>(OnMyMessageHandler3); }
static async Task OnPing(PingCommand ping) { logger.Info($"ping {ping.Id}"); await hub.Publish(new PingReplay() { Id = ping.Id }); }
public async Task Predicate() { var hub = new MetaPubSub(); hub.Subscribe <MyMessage>(OnMyMessageHandler, OnMyMessagePredicate); var message = new MyMessage { LogSeverity = MetaLogErrorSeverity.Info }; await hub.Publish(message); Assert.IsTrue(message.DeliveredCount == 0); message = new MyMessage { LogSeverity = MetaLogErrorSeverity.Error }; await hub.Publish(message); Assert.IsTrue(message.DeliveredCount == 1); await hub.Unsubscribe <MyMessage>(OnMyMessageHandler); }
async Task BasicExample() { // hub creation var hub = new MetaPubSub(); // subscribing to MyMessage hub.Subscribe <MyMessage>(OnMyMessage); // publishing a message await hub.Publish(new MyMessage()); // unsubscribing await hub.Unsubscribe <MyMessage>(OnMyMessage); }
// subscribes on server and receives a message public async Task SendMessageToClient() { var pipeName = Guid.NewGuid().ToString(); var clientConnectedEvent = new ManualResetEventSlim(); var @event = new ManualResetEventSlim(); int recvCount = 0; Task Handler(MyMessage x) { if (++recvCount == 10) { @event.Set(); } return(Task.CompletedTask); } // creating remote hub var t = Task.Run(async() => { var hub = new MetaPubSub(); hub.StartServer(pipeName); // wait for the subscriber clientConnectedEvent.Wait(5000); // publishing a message at the remote hub for (int i = 0; i < 10; i++) { await hub.Publish(new MyMessage()); } }); // local hub creation var hub = new MetaPubSub(); await hub.ConnectToServer(pipeName); await hub.SubscribeOnServer <MyMessage>(Handler); // delay allowing the server to process the subscription request await Task.Delay(100); clientConnectedEvent.Set(); @event.Wait(5000); // unsubscribing await hub.Unsubscribe <MyMessage>(Handler); Assert.IsTrue(@event.IsSet && recvCount == 10); }
// message filtering - you can define a predicate to subscribe only those messages you want to process async Task MessageFilteringExample() { var hub = new MetaPubSub(); // subscribing to MyMessage with a predicate that selects only error and critical messages hub.Subscribe <MyMessage>(OnMyMessage, m => m.LogSeverity == MetaLogErrorSeverity.Error || m.LogSeverity == MetaLogErrorSeverity.Critical); // this message will be filtered and not handled var message1 = new MyMessage { LogSeverity = MetaLogErrorSeverity.Info }; await hub.Publish(message1); // this message will be handled var message2 = new MyMessage { LogSeverity = MetaLogErrorSeverity.Error }; await hub.Publish(message2); }
// subscribed twice but delivered only once public async Task Basic() { var hub = new MetaPubSub(); var message = new MyMessage(); await hub.Publish(message); Assert.IsTrue(message.DeliveredCount == 0); hub.Subscribe <MyMessage>(OnMyMessageHandler); hub.Subscribe <MyMessage>(OnMyMessageHandler); message = new MyMessage(); await hub.Publish(message); Assert.IsTrue(message.DeliveredCount == 1); await hub.Unsubscribe <MyMessage>(OnMyMessageHandler); message = new MyMessage(); await hub.Publish(message); Assert.IsTrue(message.DeliveredCount == 0); }
// exceptions handling - all exceptions raised when a message processing by subscribers can be caught by the publisher as an AggregateException async Task ExceptionHandlingExample() { var hub = new MetaPubSub(); try { var message = new MyMessage { DeliverAtLeastOnce = true, }; // publishing a message when no one subscribed - NoSubscribersException //await hub.Publish(message); // publishing a message when no one subscribed and Timeout > 0 - TimeoutException //message.Timeout = 100; //await hub.Publish(message); hub.Subscribe <MyMessage>(OnMyMessageHandlerWithException); // publishing a message await hub.Publish(message); } catch (NoSubscribersException ex) { // No one is subscribed to this message and (message.DeliverAtLeastOnce == true and message.Timeout == 0) Console.WriteLine($"Exception {ex.GetType()}: {ex.Message}"); } catch (TimeoutException ex) { // No one is subscribed to this message and (message.DeliverAtLeastOnce == true and message.Timeout > 0) Console.WriteLine($"Exception {ex.GetType()}: {ex.Message}"); } catch (AggregateException ex) { // All exceptions raised when a message processing by subscribers // can be caught by the publisher as an AggregateException. // If some of the subscribers throw an exception, other subscribers // continues to process the message. Console.WriteLine($"Exception {ex.GetType()}: {ex.Message}"); foreach (var innerEx in ex.InnerExceptions) { Console.WriteLine($"\tInner Exception {innerEx.GetType()}: {innerEx.Message}"); } } await hub.Unsubscribe <MyMessage>(OnMyMessageHandlerWithException); }
public async Task Test_MultiProcess() { var hub = new MetaPubSub(); Task Handler(MyMessage x) { hub.Publish(new MyEvent() { SomeId = x.SomeId }); return(Task.CompletedTask); } hub.Subscribe <MyMessage>(Handler); var t1 = Task.Run(async() => { for (int i = 0; i < 100; i++) { var message = new MyMessage { SomeId = i, ResponseTimeout = 1000 }; var res = await hub.Process <MyEvent>(message, x => x.SomeId == i); Assert.IsNotNull(res); Assert.IsTrue(res.SomeId == i); } }); var t2 = Task.Run(async() => { for (int i = 100; i < 200; i++) { var message = new MyMessage { SomeId = i, ResponseTimeout = 1000 }; var res = await hub.Process <MyEvent>(message, x => x.SomeId == i); Assert.IsNotNull(res); Assert.IsTrue(res.SomeId == i); } }); await Task.WhenAll(t1, t2); }
void SelectFirmware() { OpenFileDialog ofd = new OpenFileDialog { InitialDirectory = string.IsNullOrWhiteSpace(FirmwareFilePath) ? string.Empty : Path.GetDirectoryName(FirmwareFilePath), Filter = "Firmware Image file | *.img" }; if (ofd.ShowDialog() == true) { FirmwareFilePath = ofd.FileName; } if (IsFirmwareSelected) { _hub.Publish(new StartDiscoveryCommand()); } }
public async Task Test_Process() { var hub = new MetaPubSub(); Task Handler(MyMessage x) { hub.Publish(new MyEvent()); return(Task.CompletedTask); } hub.Subscribe <MyMessage>(Handler); var message = new MyMessage { LogSeverity = MetaLogErrorSeverity.Info, DeliverAtLeastOnce = true, Timeout = 100 }; var res = await hub.Process <MyEvent>(message, 100); Assert.IsNotNull(res); }
async Task BasicExample() { int count = 0; Task Handler(MyMessage x) { count++; return(Task.CompletedTask); } // Creating the server hub. // The server and the client hubs should be created in separate processes, // this example is for demo only. var serverHub = new MetaPubSub(); // Starting the hub as a server named 'Meta'. serverHub.StartServer("Meta"); // Client hub creation. There are can be several hubs connected to the same server. var clientHub = new MetaPubSub(); // Connecting to the remote server. await clientHub.ConnectToServer("Meta"); // Subscribing to MyMessage on the server and locally at the same time. await clientHub.SubscribeOnServer <MyMessage>(Handler); // The server publishes a message. await serverHub.Publish(new MyMessage()); // Client hub publishes a message and it will be received locally without being sent to the server. await clientHub.Publish(new MyMessage()); // Client hub sends a message to the server where it will be published and sent back. await clientHub.PublishOnServer(new MyMessage()); // All three messages should be received. Debug.Assert(count == 3); // Unsubscribing both on the server-side and locally. await clientHub.Unsubscribe <MyMessage>(Handler); }
public async Task NoSubscribersException() { var pipeName = Guid.NewGuid().ToString(); var clientConnectedEvent = new ManualResetEventSlim(); var @event = new ManualResetEventSlim(); // creating remote hub var t = Task.Run(async() => { var hub = new MetaPubSub(); hub.StartServer(pipeName); // wait for the subscriber clientConnectedEvent.Wait(5000); try { // publishing a message at the remote hub await hub.Publish(new MyMessage() { DeliverAtLeastOnce = true }); } catch (NoSubscribersException) { @event.Set(); } }); // local hub creation var hub = new MetaPubSub(); await hub.ConnectToServer(pipeName); // delay allowing the server process the connection await Task.Delay(100); clientConnectedEvent.Set(); @event.Wait(5000); Assert.IsTrue(@event.IsSet); }
// request-response pattern - send a message and wait for the response as a single awaitable method, without need to Subscribe/Unsubscribe to the response message public static async Task ProcessExample() { var hub = new MetaPubSub(); // This handler should be placed somewhere in another module. // It processes MyMessage and publishes a MyEvent as a result. Task Handler(MyMessage x) { hub.Publish(new MyEvent()); return(Task.CompletedTask); } hub.Subscribe <MyMessage>(Handler); try { // This method will publish MyMessage and wait for MyEvent one second. // If the event will not arrive in a specified timeout the TimeoutException will be thrown. var message = new MyMessage { DeliverAtLeastOnce = true, WaitForSubscriberTimeout = 100, ResponseTimeout = 1_000 }; MyEvent res = await hub.Process <MyEvent>(message); Console.WriteLine($"Received MyEvent at {DateTime.Now:HH:mm:ss.fff}"); } catch (NoSubscribersException ex) { // no one is listening Console.WriteLine($"Exception {ex.GetType()}: {ex.Message}"); } catch (TimeoutException ex) { Console.WriteLine($"Exception {ex.GetType()}: {ex.Message}"); } }
public async Task Test_Process() { var hub = new MetaPubSub(); Task Handler(MyMessage x) { Task.Run(async() => { await Task.Delay(10); await hub.Publish(new MyEvent()); }); return(Task.CompletedTask); } hub.Subscribe <MyMessage>(Handler); var message = new MyMessage { ResponseTimeout = 2000 }; var res = await hub.Process <MyEvent>(message); Assert.IsNotNull(res); }
// Should get the NoSubscribersException if message is filtered and DeliverAtLeastOnce = true public async Task Test_DeliverAtLeastOnce_Filtered() { var hub = new MetaPubSub(); bool noSubscriberException = false; hub.Subscribe <MyMessage>(OnMyMessageHandler, OnMyMessagePredicate); var message = new MyMessage { LogSeverity = MetaLogErrorSeverity.Info, DeliverAtLeastOnce = true }; try { await hub.Publish(message); } catch (NoSubscribersException) { noSubscriberException = true; } Assert.IsTrue(noSubscriberException); Assert.IsTrue(message.DeliveredCount == 0); await hub.Unsubscribe <MyMessage>(OnMyMessageHandler); }
// asynchronous waiting for a specified message by a single method call, without need to Subscribe/Unsubscribe to this message public static async Task WhenExample() { var hub = new MetaPubSub(); // publishing a MyEvent with 500 ms delay var t = Task.Run(async() => { await Task.Delay(500); await hub.Publish(new MyEvent()); }); try { // This method will wait for MyEvent one second. // If the event will not arrive in a specified timeout the TimeoutException will be thrown. MyEvent res = await hub.When <MyEvent>(millisecondsTimeout : 1000); Console.WriteLine($"Received MyEvent at {DateTime.Now:HH:mm:ss.fff}"); } catch (TimeoutException ex) { Console.WriteLine($"Exception {ex.GetType()}: {ex.Message}"); } }
public MainWindowViewModel(MetaPubSub hub) { // default value -33 is to much and picks up devices from very far SdkConfig.TapProximityUnlockThreshold = -29; SdkConfig.ConnectDeviceTimeout = 5_000; SdkConfig.DeviceInitializationTimeout = 5_000; _hub = hub; _log = new EventLogger("Maintenance"); _hub.Subscribe <AdvertismentReceivedEvent>(OnAdvertismentReceived); _hub.Subscribe <DeviceConnectedEvent>(OnDeviceConnected); _hub.Subscribe <ClosingEvent>(OnClosing); ConnectionManager = new ConnectionManagerViewModel(_log, _hub); HideezServiceController = new HideezServiceController(_log, _hub); SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; if (IsFirmwareSelected) { _hub.Publish(new StartDiscoveryCommand()); } }