Reset Observable timer if an operation called - c#

I am newbie with Reactive Extensions but What is the best way to implement below scenario using Reactive Extensions:
1- Subscribe an event for every minute in constructor
2- if an operation get called then that subscriber get reset
3- if nothing happened or that operation won't be called for a minute the event in step 1 get fired
Something like this:
public class ImportClient : Carrier<IImportService>, IImportService
{
IObservable<long> proxyCleaner;
void DisposeProxy(long interval)
{
this.Close();
//Dispos proxy
}
public void RunDisposeTimer()
{
proxyCleaner = Observable.Interval(TimeSpan.FromMinutes(1));
proxyCleaner.Subscribe(DisposeProxy);
}
public ImportClient(String endpointConfigurationName) : base(endpointConfigurationName)
{
RunDisposeTimer();
}
public Attach_DTO_OUT AttachImage(AttachImage_DTO_IN source_C)
{
//Reset timer here
//Reset proxyCleaner
using (OperationContextScope scope = new OperationContextScope(this.InnerChannel))
{
AddMessageHeader<Token>(Token);
return base.Channel.AttachImage(source_C);
}
}
}
because my WCF service is Session Full I need to dispose it manually after specific time.
UPDATE:
I think it is possible to do with ObservableCollection but how:
private ObservableCollection<string> collection;
public void RunDisposeTimer()
{
collection = new ObservableCollection<string>();
collection.CollectionChanged += Collection_CollectionChanged;
}
private void Collection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
//Here reset timer
throw new NotImplementedException();
}

Related

How to unit test methods in windows form class?

I have a developing a c# windows form application and I have a method that exists inside the main form class.
Imagine methodA as part of the main form class.
public void methodA() {
A.someMethod();
B.someMethod();
// some more code
if (someCondition) {
// execute some code
}
// initialize timer and set event handler for timer
// run new thread
}
class A {
someMethod() {...}
}
class B {
someMethod() {...}
}
How would I run tests to test the branch logic of this methodA (isCondition)? since it involves initializing timer and running threads. Can i only verify the logic while doing system test ? I dont think it is possible to mock the timer and threading function.
Thank you !
Of course you can mock the timer. This is by creating a new interface, say, ITimerWrapper and implement it by using the concrete Timer class. Basically a wrapper of the Timer class. Then use that instead of the concrete Timer class you have.
Something in the tune of:
public partial class Form1 : Form
{
private readonly ITimerWrapper _timerWrapper;
public Form1(ITimerWrapper timerWrapper)
{
InitializeComponent();
this._timerWrapper = timerWrapper; // of course this is done via dependency injection
this._timerWrapper.Interval = 1000;
}
private void Form1_Load(object sender, EventArgs e)
{
// now you can mock this interface
this._timerWrapper.AddTickHandler(this.Tick_Event);
this._timerWrapper.Start();
}
private void Tick_Event(object sender, EventArgs e)
{
Console.WriteLine("tick tock");
}
}
public interface ITimerWrapper
{
void AddTickHandler(EventHandler eventHandler);
void Start();
void Stop();
int Interval { get; set; }
}
public class TimerWrapper : ITimerWrapper
{
private readonly Timer _timer;
public TimerWrapper()
{
this._timer = new Timer();
}
public int Interval
{
get
{
return this._timer.Interval;
}
set
{
this._timer.Interval = value;
}
}
public void AddTickHandler(EventHandler eventHandler)
{
this._timer.Tick += eventHandler;
}
public void Start()
{
this._timer.Start();
}
public void Stop()
{
this._timer.Stop();
}
}
Then for the spinning of a new thread, that's also testable by doing the same thing.
Bottomline is to have an interface to separate concerns and mock the interface on your unit test.

Reset and Dispose observable subscriber, Reactive Extensions

Suppose I have this :
public class UploadDicomSet
{
public UploadDicomSet()
{
var cachCleanTimer = Observable.Interval(TimeSpan.FromMinutes(2));
cachCleanTimer.Subscribe(CheckUploadSetList);
//Start subscriber
}
void CheckUploadSetList(long interval)
{
//Stop and dispose subscriber
}
public void AddDicomFile(SharedLib.DicomFile dicomFile)
{
//Renew subscriber, call CheckUploadSetList 2 minutes later
}
}
1- in CheckUploadSetList I want to dispose or finish observable
2- in AddDicomFile I want to reset it
as comment in methods.
UPDATE:
I can do it by Timer as:
public class UploadDicomSet : ImportBaseSet
{
Timer _timer;
public UploadDicomSet()
{
_timer = new Timer(CheckUploadSetList, null, 120000, Timeout.Infinite);
}
void CheckUploadSetList(object state)
{
Logging logging = new Logging(LogFile);
try
{
_timer.Dispose(); //Stop the subscription
//dispose everything
}
catch (Exception exp)
{
logging.Log(ErrorCode.Error, "CheckUploadSetList() failed..., EXP:{0}", exp.ToString());
}
}
public void AddDicomFile(SharedLib.DicomFile dicomFile)
{
_timer.Change(120000, Timeout.Infinite);
}
}
Thanks in advance.
You should use Switch() for this kind of thing.
Something like this:
public class UploadDicomSet : ImportBaseSet
{
IDisposable subscription;
Subject<IObservable<long>> subject = new Subject<IObservable<long>>();
public UploadDicomSet()
{
subscription = subject.Switch().Subscribe(s => CheckUploadSetList(s));
subject.OnNext(Observable.Interval(TimeSpan.FromMinutes(2)));
}
void CheckUploadSetList(long interval)
{
subject.OnNext(Observable.Never<long>());
// Do other things
}
public void AddDicomFile(SharedLib.DicomFile dicomFile)
{
subject.OnNext(Observable.Interval(TimeSpan.FromMinutes(2)));
// Reset the subscription to go off in 2 minutes from now
// Do other things
}
}
Using Reactive Extension for just some timer function seems a bit overkill to me. Why not just use an ordinary timer for this, and start/stop it at given times?
Let me give an idea.
public class UploadDicomSet : ImportBaseSet
{
IDisposable subscription;
public void CreateSubscription()
{
var cachCleanTimer = Observable.Interval(TimeSpan.FromMinutes(2));
if(subscription != null)
subscription.Dispose();
subscription = cachCleanTimer.Subscribe(s => CheckUploadSetList(s));
}
public UploadDicomSet()
{
CreateSubscription();
// Do other things
}
void CheckUploadSetList(long interval)
{
subscription.Dispose(); // Stop the subscription
// Do other things
}
public void AddDicomFile(SharedLib.DicomFile dicomFile)
{
CreateSubscription(); // Reset the subscription to go off in 2 minutes from now
// Do other things
}
}
Background material
I really can recommend these sites:
http://www.introtorx.com/
http://rxwiki.wikidot.com/101samples

How can I create a collection of items that

Let me try to explain the design pattern I'm looking to implement. I have a Queue<Item> or some other collection of Items that needs to be processed by some method
static void Process(Item item)
{
// ...
}
They can be processed synchronously or asynchronously.
This queue will be getting items added to it periodically, because I have some method like
static void AddWorkToQueue()
{
// ...
}
that gets run on a timer
timer.Elapsed += AddWorkToQueue();
So what I need is some type "continuous while loop" that stops whenever the queue is empty.
How can I use C#.NET to do this in the best way? Are there any built-in libraries for solving this type of problem?
You could create a custom queue class and change it's listener:
public class CustomQueue : Queue<object>
{
public event EventHandler FirstItemInserted;
protected virtual void OnFirstItemInserted()
{
FirstItemInserted?.Invoke(this, EventArgs.Empty);
}
//Modified Enqueue method.
public new void Enqueue(object obj)
{
//Call the listener every time an item is inserted into the empty queue.
if (Count == 0)
{
base.Enqueue(obj);
OnFirstItemInserted();
}
else
base.Enqueue(obj);
}
}
The "Enqueue" method was changed to call the listener after each first insert.
All you'll need to do is to call a method to consume each item of your queue as long as there are items to dequeue.
class MyProgram
{
private static CustomQueue MyQueue;
public MyProgram()
{
MyQueue = new CustomQueue();
MyQueue.FirstItemInserted += ConsumeQueue;
//Activate timer...
}
private static void ConsumeQueue(object sender, EventArgs e)
{
object item;
while (MyQueue.Count > 0)
{
item = MyQueue.Dequeue();
//Do something...
}
}
}
You can use BufferBlock<Item> from TPL DataFlow (https://msdn.microsoft.com/en-us/library/hh160414(v=vs.110).aspx):
using System.Threading.Tasks.Dataflow;
static void AddWorkToQueue()
{
queue.Send(new Item());
}
static async void MainLoop()
{
while (true) // may be you need some cancellation token to trigger end of processing
{
var item = await queue.ReceiveAsync();
ProcessItem(item);
}
}

Observer pattern with timer

I have used Observer Pattern for my application.
I have a subject which has one System.Timers.Timer object in it named 'tmr'. The tick event of this timer fires after every 60 seconds. On this tick event I will notify all my observers that are attached to my subject. I have used a for-loop to iterate throught my Observers List & then fire the Observers Update method.
Assume i have 10 observers attached to my subject.
Each observer takes 10 seconds to complete its processing.
Now notification being done in a for-loop causes the last Observer's Update method to be called after 90seconds. i.e. Next Observer Update method is called only after previous one has completed its processing.
But this is not what i wanted in my application. I need all my observers Update method to be fired instantly when the timer tick occurs. So that no observer has to wait. I hope this can be done by Threading.
So, I modified code to,
// Fires the updates instantly
public void Notify()
{
foreach (Observer o in _observers)
{
Threading.Thread oThread = new Threading.Thread(o.Update);
oThread.Name = o.GetType().Name;
oThread.Start();
}
}
But I have two doubts in my mind,
If there are 10 observers
And my timer interval is 60 seconds
Then the statement new Thread() will fire 600 times.
Is it efficient and recommended to create new threads on every timer tick ?
What if my observers are taking too much time to complete their update logic i.e. goes more than 60seconds. Means the timer tick occurs before the observers are updated. How can i control this ?
I can post sample code.. if required...
The code i used..
using System;
using System.Collections.Generic;
using System.Timers;
using System.Text;
using Threading = System.Threading;
using System.ComponentModel;
namespace singletimers
{
class Program
{
static void Main(string[] args)
{
DataPullerSubject.Instance.Attach(Observer1.Instance);
DataPullerSubject.Instance.Attach(Observer2.Instance);
Console.ReadKey();
}
}
public sealed class DataPullerSubject
{
private static volatile DataPullerSubject instance;
private static object syncRoot = new Object();
public static DataPullerSubject Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new DataPullerSubject();
}
}
return instance;
}
}
int interval = 10 * 1000;
Timer tmr;
private List<Observer> _observers = new List<Observer>();
DataPullerSubject()
{
tmr = new Timer();
tmr.Interval = 1; // first time to call instantly
tmr.Elapsed += new ElapsedEventHandler(tmr_Elapsed);
tmr.Start();
}
public void Attach(Observer observer)
{
_observers.Add(observer);
}
public void Detach(Observer observer)
{
_observers.Remove(observer);
}
// Fires the updates instantly
public void Notify()
{
foreach (Observer o in _observers)
{
Threading.Thread oThread = new Threading.Thread(o.Update);
oThread.Name = o.GetType().Name;
oThread.Start();
}
}
private void tmr_Elapsed(object source, ElapsedEventArgs e)
{
tmr.Interval = interval;
tmr.Stop(); // stop the timer until all notification triggered
this.Notify();
tmr.Start();//start again
}
}
public abstract class Observer
{
string data;
public abstract void Update();
public virtual void GetDataFromDBAndSetToDataSet(string param)
{
Console.WriteLine("Processing for: " + param);
data = param + new Random().Next(1, 2000);
Threading.Thread.Sleep(10 * 1000);//long work
Console.WriteLine("Data set for: " + param);
}
}
public sealed class Observer1 : Observer
{
private static volatile Observer1 instance;
private static object syncRoot = new Object();
public static Observer1 Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Observer1();
}
}
return instance;
}
}
Observer1()
{
}
public override void Update()
{
base.GetDataFromDBAndSetToDataSet("Observer1");
}
}
public sealed class Observer2 : Observer
{
private static volatile Observer2 instance;
private static object syncRoot = new Object();
public static Observer2 Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Observer2();
}
}
return instance;
}
}
Observer2()
{
}
public override void Update()
{
base.GetDataFromDBAndSetToDataSet("Observer2");
}
}
}
Thanks & kind regards.
Using new Thread is discouraged. Use Task or Task<T>
Your best attempt at creating an Observable pattern framework will probably only come close to Rx. Use that which solves the problems you mentioned (i.e. if processing takes too much time). Rx will give you huge flexibility in defining your observable scenarios.
1) You can use Threads from the ThreadPool via ThreadPool.QueueUserWorkItem or you can use Tasks
2) You have to synchronize your Methods.
Alternatively, the observers could implement Update in a non-blocking way.
That is, Update always returns immediately. Then it is the responsibility of the Observer objects to perform their work in a new thread if necessary.
I'm not sure if this helps in your scenario - I don't know what your 'Observers' are, but then maybe you don't know either?

C#: Triggering an Event when an object is added to a Queue

I need to be able to trigger a event whenever an object is added to a Queue<Delegate>.
I created a new class that extends Queue:
public delegate void ChangedEventHandler(object sender, EventArgs e);
public class QueueWithChange<Delegate> : Queue<Delegate>
{
public event ChangedEventHandler Changed;
protected virtual void OnChanged(EventArgs e) {
if (Changed != null)
{
Changed(this, e);
}
}
}
And then attached the event from another class, like such:
QueueWithChange<TimerDelegate> eventQueue = new QueueWithChange<TimerDelegate>();
//
eventQueue.Changed += new ChangedEventHandler(delegate(object s, EventArgs ex) {
//This event is not being triggered, so this code is unreachable atm...and that is my problem
if (eventQueue.Count > 0)
{
eventQueue.Dequeue().Invoke(new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(5) });
actionTimer.Stop();
}
});
But whenever I enqueue an object (eventQueue.Enqueue(something)), the attached event is not being fired.
What am I missing here?
If you mean the non-generic Queue class, then you can just override Enqueue:
public override void Enqueue(object obj)
{
base.Enqueue(obj);
OnChanged(EventArgs.Empty);
}
However, if you mean the generic Queue<T> class, then note that there is no suitable virtual method to override. You might do better to encapsulate the queue with your own class:
(** important edit: removed base-class!!! **)
class Foo<T>
{
private readonly Queue<T> queue = new Queue<T>();
public event EventHandler Changed;
protected virtual void OnChanged()
{
if (Changed != null) Changed(this, EventArgs.Empty);
}
public virtual void Enqueue(T item)
{
queue.Enqueue(item);
OnChanged();
}
public int Count { get { return queue.Count; } }
public virtual T Dequeue()
{
T item = queue.Dequeue();
OnChanged();
return item;
}
}
However, looking at your code, it seems possible that you are using multiple threads here. If that is the case, consider a threaded queue instead.
I just did write up on what I call a TriggeredQueue. It's inspired the answer by Marc Gravell.
You can find my post here: http://joesauve.com/triggeredqueuet
And the Gist here: http://gist.github.com/jsauve/b2e8496172fdabd370c4
It has four events:
WillEnqueue
WillDequeue
DidEnqueue
DidDequeue
You can hook into any of these like so:
YourQueue.WillEnqueue += (sender, e) => {
// kick off some process
};
YourQueue.DidEnqueue += (sender, e) => {
// kick off some process
// e.Item provides access to the enqueued item, if you like
};
YourQueue.WillDequeue += (sender, e) => {
// kick off some process
};
YourQueue.DidDequeue += (sender, e) => {
// kick off some process
// e.Item provides access to the dequeued item, if you like
};
One neat trick is that you can use the DidDequeue method to kick off some process to ensure that the queue is full by making a web request or loading some data from a filesystem, etc. I use this class in Xamarin mobile apps to ensure that data and images are pre-cached in order to provide a smooth user experience, instead of loading images AFTER they scroll onto the screen (like you might see in Facebook and countless other apps).
try
public new void Enqueue(Delegate d)
{
base.Enqueue(d);
OnChanged(EventArgs.Empty);
}
You have to override Enqueue, to call OnChanged.

Categories

Resources