So I'm just playing around with RX and learning it. I started playing with Events, and wanted to know how to subscribe to events, and process the results in batches asynchronously. Allow me to explain with code:
Simple class that raises events:
public class EventRaisingClass
{
public event EventHandler<SomeEventArgs> EventOccured;
//some other code that raises event...
}
public class SomeEventArgs : EventArgs
{
public SomeEventArgs(int data)
{
this.SomeArg = data;
}
public int SomeArg { get; private set; }
}
Then my Main:
public static void Main(string[] args)
{
var eventRaiser = new EventRaisingClass();
IObservable<IEvent<SomeEventArgs>> observable =
Observable.FromEvent<SomeEventArgs>(e => eventRaiser.EventOccured += e, e => eventRaiser.EventOccured -= e);
IObservable<IList<IEvent<SomeEventArgs>>> bufferedEvents = observable.BufferWithCount(100);
//how can I subscribte to bufferedEvents so that the subscription code gets called Async?
bufferedEvents.Subscribe(list => /*do something with list of event args*/); //this happens synchrounously...
}
As you can see in my comments, when you just call subscribe like that, all the subscription code happens synchronously. Is there a way out of the box using RX to have the Subscribe be called on different threads whenever there's a new batch of events to work on?
bufferedEvents.ObserveOn(Scheduler.TaskPool).Subscribe(...
SubscribeOn is to specify the schedule on which so-called "subscription side effects" are happening. For example, your observable can open a file each time somebody subscribes.
ObserveOn is to specify the schedule on which the call to the observer will happen every time when there is a new value. In practice, it is used more often than SubscribeOn.
I believe you're looking for SubscribeOn or ObserveOn, passing an IScheduler. There are several schedulers built-in under System.Concurrency; some of them use whatever thread is current, and others use specific threads.
This video has more info on the scheduler concept.
The Rx team also recently released a hands-on labs document which is the closest thing to a tutorial right now.
Related
This question already has answers here:
Where is the WPF Timer control?
(4 answers)
Closed 4 years ago.
How can I create an async structure that will be consist of stack of delegates and popping them and invoke each of them every N ms?
The problem is now I have lot delegates that invoke changes on ui and it causes ui freezing so how to make this delegates invoking every N ms if stack is not empty.
Now I have this
class CallbackRestriction
{
private Stack<KeyValuePair<Action<ImageWrapper>, ImageWrapper>> _callbackList =
new Stack<KeyValuePair<Action<ImageWrapper>, ImageWrapper>>();
public void AddCallback(Action<ImageWrapper> action, ImageWrapper payload)
{
_callbackList.Push(new KeyValuePair<Action<ImageWrapper>, ImageWrapper>(action, payload));
}
private async Task CallbackEmitLoop()
{
while (true)
{
await Task.Delay(TimeSpan.FromMilliseconds(20));
try
{
var callback = _callbackList.Pop();
callback.Key.Invoke(callback.Value);
}
catch (Exception e)
{
await Task.Delay(200);
}
}
}
}
But how can I make CallbackEmitLoop start in the background? Or any other solution for this?
Update 1
I do not need the dispather timer because is tighten with wpf and maybe for "timer" things I should use synchronization context. And I don't have problems with calling to my collection from others context because collection can be made concurrency ready. I need something like a valve that would restrict invoking delegates once they have been added. So how I described problem above I can get a lot of "updates"(delegates) at one time and if I just apply them(call delegates) the ui thread would be busy significant time that will cause freezing and because of this I somehow should keep times before apply next "update".
Here's one way. The code below uses your CallbackRestriction class and my dummy implementation of ImageWrapper. I've made the CallbackEmitLoop method public so that my window can start it with Task.Run.
Because I maintain the delegate emitter instance in my window, it will run as long as the window is alive. A real app would likely run it from some other service class.
The callback needs to use Dispatcher to invoke code on the UI thread if it needs to work with WPF UI elements because the Task runs on a thread pool thread, and any delegate invocations will run on that thread too.
Regarding the comment that this may be a duplication question, the OP is asking how to have a running Task invoke delegates that interact with the UI, and while DispatcherTimer is certainly a reasonable approach, it doesn't address the OP's question, nor does it offer an explanation as to why DispatcherTimer would be a more appropriate implementation.
// My dummy ImageWrapper
public class ImageWrapper
{
public string Val { get; set; }
}
public partial class MainWindow
{
private CallbackRestriction _restriction = new CallbackRestriction();
public MainWindow()
{
InitializeComponent();
_restriction.AddCallback(MyCallback, new ImageWrapper() {Val = "Hello"});
Task.Run(_restriction.CallbackEmitLoop);
}
private void MyCallback(ImageWrapper wrapper)
{
// since the callback will be running on the
// thread associated with the task, if you
// want to interact with the UI in the callback
// you need to use Dispatcher
Dispatcher.BeginInvoke(new Action(() =>
{
Debug.WriteLine(wrapper.Val);
}));
}
}
I'm working on a software where software issues commands for hardware panel and once a command is issued, its response received after few seconds . there are different functions for different hardware commands like
public void FunctionA()
{
StartCommandA();
}
and other functions on the same pattern that will be used to run other commands.
FunctionB();
FunctionC();
Once we receive the response of command A , I invoke the other function from the response but this approach is not good as per design pattern practices.
All i want to do is to make a list of functions and invoke all these functions one after other, But next function will be called once i get response of first functions.
I tried this by using Multicast delegate but I'm unable to find out how we can call get the list of functions once i add all functions to that delegates. This is what i'm trying do since.
FunList funList_ConfigAndSerialTests = new FunList(StartSerialTest);
funList_ConfigAndSerialTests += StartSerialTest;
funList_ConfigAndSerialTests += StartMsrTest;
funList_ConfigAndSerialTests += StartContactLessTest;
//funList_ConfigAndSerialTests.Invoke();
Delegate[] del = funList_ConfigAndSerialTests.GetInvocationList();
foreach (Delegate item in funList_ConfigAndSerialTests.GetInvocationList())
{
while (true)
{
if (IsResponseReceived == true)
{
// Call function here
}
}
}
The simplest way to do this is to call the functions one by one:
FunctionA();
FunctionB();
FunctionC();
Each method will be called only after the previous has returned.
But you said you want to call the next function after the previous one has a response. Now that sounds like your functions run asynchronously. I strongly suggest you use the async keyword to mark your functions and make them return a Task<ResonseType>. You can learn about this here.
You'll then be able to do something like this:
await FunctionA(); // you obviously want to do something with the returned response
// I do not know your requirements so I did not show that part
await FunctionB();
await FunctionC();
It seems what you're trying to achieve is what Events are for. In the class, where the handlers (FunctionA, FunctionB, ...) are defined create an event instance as follows:
public class MyClass
{
private event Action Event;
public void RegisterHandlers()
{
Event += FuncA;
Event += FuncB;
Event();
}
public void HandleCommand()
{
this.Event();
}
private void FuncA() { /*...*/ }
private void FuncB() { /*...*/ }
}
The simple call to Events() will actually result in all the registered handlers to be invoked in the order they've been registered.
I'm quite new to C# and certainly OOP concepts.. so forgive the stupidity of my question.
I have a system I wish to communicate with, It has a number of commands that can be called with an associated response. (Communication is done via TCP/IP or Serial) (I implemented an Interface with SendMessage so that I can use multiple transport mechanisms)
I want to create a method for each command and then expose these, which is simple enough. The device also lets say 'broadcasts' messages as well which I want to act on, so I was using an event handler for this which works well..
At the moment in the event handler I catch OK and ERROR style messages, but ideally I would like to also be able to send the command from the above method and catch an error and return a bool value based on the command.
Can anyone think of a way I can do something like this and point me in the right direction?
Thanks
David
You can use helper to wait for event. Some ugly code from past:
public class ComWait
{
ManualResetEvent _waitEvent;
SomeEvent _eventHandler;
public ComWait()
{
_waitEvent = new ManualResetEvent(false);
_eventHandler = new SomeEvent(Watch);
}
void Watch()
{
_waitEvent.Set();
}
public bool Wait(int time = 3000)
{
_waitEvent.Reset();
SomeEvent += _eventHandler;
bool result = _waitEvent.WaitOne(time, false);
SomeEvent -= _eventHandler;
return result;
}
}
Usage is
ComWait wait = new ComWait();
if(!wait.Wait())
return; // timeout
// process
It will simply block synchronous method until event is rised or timeout occurs. It should be easy to add parameters: to unblock on specific event and to pass event handler parameters back to caller.
Otherwise I would simply have method inside communication class to use as a blocker:
readonly object _waitLock = new object();
public void Wait()
{
lock (_waitLock)
if (!Monitor.Wait(_waitLock, 3000))
throw new TimeoutException("No communications");
}
Signal at same time as you rise event:
lock (_waitLock)
Monitor.PulseAll(_waitLock);
Hello yeah I'm asking this question a second time, sorry about that but I don't know how to bump previous question. I'll explain more in depth my problem in a more completed example.
Instead of writing like 300+ Event classes in 300 class files which I may have to do if this doesn't work, so they can do little timed jobs like this example job below in a server project.
What i'm trying to avoid is writing a bunch of classes and simply just write everything more compacted in structure of whatever i'm working on.
To sum it up, i'm mixing 90% functional programming and want to give some function some delayed timed event, without creating the new timed event in a separate class then running back and forth through the files looking how everything is linked up, but this way everything can be seen so you can find bugs and whatnot much faster as everything is right in front of you, kinda like writing loop code, but with delay.
All I have right now is one thread which processes events, deletes events which have been stopped, keeps re-running events which don't stop after one cycle and of course waiting until some events can be ran.
If anyone knows a better way to do what i'm trying to do maybe some built-in C# Event system? Which is preferably simple.
class Event {
private Action action;
private bool stopped;
public Event(long tick, Action action) {
this.tick = tick;
this.action = action;
this.lastRun = Environment.TickCount;
}
public void stop() {
stopped = true;
}
public bool canRun() { //blah ignore just showing what I plan to do
if (stopped)
return false;
return (Environment.TickCount - lastRun) > tick;
}
public void run() {
this.lastRun = Environment.TickCount;
action();
}
//... other methods
}
class Test {
string t;
public void setT(string t) {
this.t = t;
}
public void stuff() {
Console.WriteLine(a);
}
}
class ImportantWork {
public static void Main(string[] args) {
someDeepMethod();
}
void someDeepMethod() {
Test t = new Test();
t.setT("secondTime");
//Here is where the problem occurs.
Server.registerEvent(new Event(5000, () => {
this.stop(); //<-- Error how I call this from this new Event instance.
stop(); //<-- Also error
//Event.stop(); //<-- haha may work if it was static but thats stupid
t.stuff();
Console.WriteLine("thirdTime");
}));
t.setT("firstTime");
t.stuff();
}
}
Expected output:
firstTime
...waits 5 seconds...
secondTime
thirdTime
I don't know how you'd be able to do that inline like that. Why can't you use some kind of set-function and make it two lines?
MyEvent newEvent;
Server.registerEvent((newEvent = new MyEvent(5000)));
newEvent.setAction(() => {
newEvent.stop();
t.stuff();
Console.WriteLine("thirdTime");
});
It seems to me like there's some kind of structural issue with your design. I'm assuming that the example you provided was not actually what you were working with, just a simple example to address the problem you're having. If it is, however, the example you're working with why don't you just add a boolean flag in the constructor to tell the instance whether or not to call this.stop() on itself - instead of requiring it specified in the Action?
Best of luck!
I have a class, that subscribes to an event via PRISMs event aggregator.
As it is somewhat hard to mock the event aggregator as noted here, I just instantiate a real one and pass it to the system under test.
In my test I then publish the event via that aggregator and then check how my system under test reacts to it. Since the event will be raised by a FileSystemWatcher during production, I want to make use of the automatic dispatch by subscribing on the UIThread, so I can update my UI once the event is raised.
The problem is, that during the test, the event never gets noticed in the system under test unless I don't subscribe on the UIThread.
I am using MSpec for my tests, which I run from inside VS2008 via TDD.Net.
Adding [RequiresSta] to my test class didn't help
Does anyone have a solution, that saves me from changing the ThreadOption during my tests (e.g. via a property - what an ugly hack)???
If you mock both the event and the Event Aggregator, and use moq's Callback, you can do it.
Here's an example:
Mock<IEventAggregator> mockEventAggregator;
Mock<MyEvent> mockEvent;
mockEventAggregator.Setup(e => e.GetEvent<MyEvent>()).Returns(mockEvent.Object);
// Get a copy of the callback so we can "Publish" the data
Action<MyEventArgs> callback = null;
mockEvent.Setup(
p =>
p.Subscribe(
It.IsAny<Action<MyEventArgs>>(),
It.IsAny<ThreadOption>(),
It.IsAny<bool>(),
It.IsAny<Predicate<MyEventArgs>>()))
.Callback<Action<MyEventArgs>, ThreadOption, bool, Predicate<MyEventArgs>>(
(e, t, b, a) => callback = e);
// Do what you need to do to get it to subscribe
// Callback should now contain the callback to your event handler
// Which will allow you to invoke the callback on the test's thread
// instead of the UI thread
callback.Invoke(new MyEventArgs(someObject));
// Assert
I really think you should use mocks for everything and not the EventAggregator. It's not hard to mock at all... I don't think the linked answer proves much of anything about the testability of the EventAggregator.
Here's your test. I don't use MSpec, but here's the test in Moq. You didn't provide any code, so I'm basing it on the linked-to code. Your scenario is a little harder than the linked scenario because the other OP just wanted to know how to verify that Subscribe was being called, but you actually want to call the method that was passed in the subscribe... something more difficult, but not very.
//Arrange!
Mock<IEventAggregator> eventAggregatorMock = new Mock<IEventAggregator>();
Mock<PlantTreeNodeSelectedEvent> eventBeingListenedTo = new Mock<PlantTreeNodeSelectedEvent>();
Action<int> theActionPassed = null;
//When the Subscribe method is called, we are taking the passed in value
//And saving it to the local variable theActionPassed so we can call it.
eventBeingListenedTo.Setup(theEvent => theEvent.Subscribe(It.IsAny<Action<int>>()))
.Callback<Action<int>>(action => theActionPassed = action);
eventAggregatorMock.Setup(e => e.GetEvent<PlantTreeNodeSelectedEvent>())
.Returns(eventBeingListenedTo.Object);
//Initialize the controller to be tested.
PlantTreeController controllerToTest = new PlantTreeController(eventAggregatorMock.Object);
//Act!
theActionPassed(3);
//Assert!
Assert.IsTrue(controllerToTest.MyValue == 3);
You may not like this as it may involve what you feel is an "ugly hack", but my preference IS to use a real EventAggregator rather than mocking everything. While ostensibly an external resource, the EventAggregator runs in memory and so does not require much set-up, clear down, and is not a bottle neck like other external resources such as databases, web-services, etcetera would be and therefore I feel it is appropriate to use in a unit test. On that basis I have used this method to overcome the UI thread issue in NUnit with minimal change or risk to my production code for the sake of the tests.
Firstly I created an extension method like so:
public static class ThreadingExtensions
{
private static ThreadOption? _uiOverride;
public static ThreadOption UiOverride
{
set { _uiOverride = value; }
}
public static ThreadOption MakeSafe(this ThreadOption option)
{
if (option == ThreadOption.UIThread && _uiOverride != null)
return (ThreadOption) _uiOverride;
return option;
}
}
Then, in all my event subscriptions I use the following:
EventAggregator.GetEvent<MyEvent>().Subscribe
(
x => // do stuff,
ThreadOption.UiThread.MakeSafe()
);
In production code, this just works seamlessly. For testing purposes, all I have to do is add this in my set-up with a bit of synchronisation code in my test:
[TestFixture]
public class ExampleTest
{
[SetUp]
public void SetUp()
{
ThreadingExtensions.UiOverride = ThreadOption.Background;
}
[Test]
public void EventTest()
{
// This doesn't actually test anything useful. For a real test
// use something like a view model which subscribes to the event
// and perform your assertion on it after the event is published.
string result = null;
object locker = new object();
EventAggregator aggregator = new EventAggregator();
// For this example, MyEvent inherits from CompositePresentationEvent<string>
MyEvent myEvent = aggregator.GetEvent<MyEvent>();
// Subscribe to the event in the test to cause the monitor to pulse,
// releasing the wait when the event actually is raised in the background
// thread.
aggregator.Subscribe
(
x =>
{
result = x;
lock(locker) { Monitor.Pulse(locker); }
},
ThreadOption.UIThread.MakeSafe()
);
// Publish the event for testing
myEvent.Publish("Testing");
// Cause the monitor to wait for a pulse, but time-out after
// 1000 millisconds.
lock(locker) { Monitor.Wait(locker, 1000); }
// Once pulsed (or timed-out) perform your assertions in the real world
// your assertions would be against the object your are testing is
// subscribed.
Assert.That(result, Is.EqualTo("Testing"));
}
}
To make the waiting and pulsing more succinct I have also added the following extension methods to ThreadingExtensions:
public static void Wait(this object locker, int millisecondTimeout)
{
lock (locker)
{
Monitor.Wait(locker);
}
}
public static void Pulse(this object locker)
{
lock (locker)
{
Monitor.Pulse(locker);
}
}
Then I can do:
// <snip>
aggregator.Subscribe(x => locker.Pulse(), ThreadOption.UIThread.MakeSafe());
myEvent.Publish("Testing");
locker.Wait(1000);
// </snip>
Again, if your sensibilities mean you want to use mocks, go for it. If you'd rather use the real thing, this works.