asp.net custom cache dependency, refresh all in at one moment - c#

I've got a custom cache dependency
class MyCacheDependency : CacheDependency
{
private const int PoolInterval = 5000;
private readonly Timer _timer;
private readonly string _readedContent;
public MyCacheDependency()
{
_timer = new Timer(CheckDependencyCallback, this, PoolInterval, PoolInterval);
_readedContent = ReadContentFromFile();
}
private void CheckDependencyCallback(object sender)
{
lock (_timer)
{
if (_readedContent != ReadContentFromFile())
{
NotifyDependencyChanged(sender, EventArgs.Empty);
}
}
}
private static string ReadContentFromFile()
{
return File.ReadAllText(#"C:\file.txt");
}
protected override void DependencyDispose()
{
if (_timer != null) _timer.Dispose();
base.DependencyDispose();
}
}
It works perfectly, but Im wondering how to make a refresh of all the object in one time. Here I put into cache 2 objects
Cache.Insert("c1", "var1", new MyCacheDependency());
Cache.Insert("c2", "vae2", new MyCacheDependency());
Its fine, but when c1 will detect change how to force c2 to don't wait 5 seconds to check but I want to call itself DependencyDispose when c1 do it.
In other words, if c1 detects change, c2 also should call DependencyDispose

Maybe you could add a static event which would be fired in your CheckDependencyCallback()-method. In your constructor for the MyCacheDependency you would then attach an eventhandler. When the event is fired you could call NotifyDependencyChanged or DependencyDispose from there. In this way all MyCacheDependency-objects would react to a change.
class MyCacheDependency : CacheDependency
{
private const int PoolInterval = 5000;
private readonly Timer _timer;
private readonly string _readedContent;
public static event EventHandler MyEvent;
public MyCacheDependency()
{
_timer = new Timer(CheckDependencyCallback, this, PoolInterval, PoolInterval);
_readedContent = ReadContentFromFile();
MyEvent += new EventHandler(MyEventHandler);
}
protected void MyEventHandler(object sender, EventArgs e) {
NotifyDependencyChanged(sender, e);
}
private void CheckDependencyCallback(object sender)
{
lock (_timer)
{
if (_readedContent != ReadContentFromFile())
{
if(MyEvent!=null)
MyEvent(sender, EventArgs.Empty);
}
}
}
private static string ReadContentFromFile()
{
return File.ReadAllText(#"C:\file.txt");
}
protected override void DependencyDispose()
{
if (_timer != null) _timer.Dispose();
base.DependencyDispose();
}
}

Related

Update a form in parallel with an installation script?

I currently have an installation "framework" that does specific things. What I need now to do is be able to call my form in parallel with my script. Something like this:
InstallationForm f = new InstallationForm();
Application.Run(f);
InstallSoftware(f);
private static void InstallSoftware(InstallationForm f) {
f.WriteToTextbox("Starting installation...");
Utils.Execute(#"C:\temp\setup.msi", #"-s C:\temp\instructions.xml");
...
f.WriteToTextbox("Installation finished");
The current way I can do this is by adding the Form.Shown handler in InstallSoftware, but that seems really messy. Is there anyway I can do this better?
Your code will not work, because Application.Run(f) returns not until the form was closed.
You may use a simplified Model/View/Controller pattern. Create an InstallationFormController class that has several events, e.g. for textual notifications to be written to your textbox. The InstallationForm registers on these events in it's OnLoad() method and then calls InstallationFormController.Initialize(). That method starts your installation (on a worker thread/task). That installation callback method fires several text events.
InstallationForm f = new InstallationForm(new InstallationFormController());
Application.Run(f);
internal class InstallationFormController
{
public event EventHandler<DataEventArgsT<string>> NotificationTextChanged;
public InstallationFormController()
{
}
public void Initialize()
{
Task.Factory.StartNew(DoInstallation);
}
private void DoInstallation()
{
...
OnNotificationTextChanged(new DataEventArgsT<string>("Installation finished"));
}
private void OnNotificationTextChanged(DataEventArgsT<string> e)
{
if(NotificationTextChanged != null)
NotificationTextChanged(this, e);
}
}
public class DataEventArgsT<T> : EventArgs
{
...
public T Data { get; set; }
}
internal class InstallationForm : Form
{
private readonly InstallationFormController _controller;
public InstallationForm()
{
InitializeComponent();
}
public InstallationForm(InstallationFormController controller) : this()
{
if(controller == null)
throw new ArgumentNullException("controller")
_controller = controller;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_controller.NotificationTextChanged += Controller_NotificationTextChanged;
_controller.Initialize();
}
protected virtual void Controller_NotificationTextChanged(object sender, DataEventArgsT<string> e)
{
if(this.InvokeRequired)
{ // call this method on UI thread!!!
var callback = new EventHandler<DataEventArgsT<string>>(Controller_NotificationTextChanged);
this.Invoke(callback, new object[] {sender, e});
}
else
{
_myTextBox.Text = e.Data;
}
}
...
}

Timer act crazy, Resets in different times not as defined

I have this class
public class ResetClock
{
public delegate void ResetFunc();
private ResetFunc m_ResetFunc;
private event ResetFunc Reseted;
private Timer m_Timer;
public ResetClock(int second)
{
double r = second * 1000;
m_Timer = new Timer(r);
m_Timer.AutoReset = false;
m_Timer.Elapsed += new ElapsedEventHandler(onTimerTick);
Reset();
}
public void SetResetMethod(ResetFunc method)
{
m_ResetFunc = method;
}
public void Terminate()
{
m_Timer.Stop();
m_Timer.Dispose();
m_Timer = null;
}
private void onTimerTick(object sender, ElapsedEventArgs e)
{
if (m_ResetFunc == null)
{
if (Reseted != null) Reseted();
}
else
{
m_ResetFunc();
}
Reset();
}
#region Public
public void Reset()
{
m_Timer.Reset();
}
#endregion
}
internal static class TimerEx{
public static void Reset(this Timer timer){
timer.Stop();
timer.Start();
}
}
My application is showing the reset page when this class reaches the seconds defined in the contractor. when a Reset() method calls, the Timer should reset the it self and begin the timer from 0.
for some reason after the application is running few days the reset event is firing after few seconds and not the number of seconds that i defined in the first application initialization
does anyone have any idea....??? I braking my head through the wall to find the answer..

variable not set by background worker on first pass

I have an observer with a background worker. Lets say the observer has the following structure:
internal class Observer
{
private readonly BackgroundWorker bw1;
internal Object target;
public Observer()
{
bw1 = new BackgroundWorker();
bw1.DoWork += bw1_DoWork;
bw1.RunWorkerCompleted += bw1_RunWorkerCompleted;
bw1.WorkerSupportsCancellation = true;
}
private void bw1_DoWork(object sender, DoWorkEventArgs e)
{
e.Result = new object(); // Query to database
}
private void bw1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
target = e.Result as object;
if (ChangedScannedValue != null)
{
ChangedScannedValue(_scannedValue);
}
}
private String _scannedValue = string.Empty;
internal delegate void OnChangedScannedValue(String scannedValue);
internal event OnChangedScannedValue ChangedScannedValue;
internal String ScannedValue
{
get { return _scannedValue; }
set
{
_scannedValue = value;
bw1.RunWorkerAsync(_scannedValue);
//ProcessScannedValue();
}
}
}
I have another class listening to the event.
public partial class myControl : UserControl
{
Observer _observer = new Observer();
public myControl()
{
InitializeComponent();
}
internal void LoadData(Observer observer)
{
_observer = observer;
_observer.ChangedScannedValue += _observer_ChangedScannedValue;
}
void _observer_ChangedScannedValue(string ScannedValue)
{
if (_observer.target != null)
{
// Do Stuff
}
else
{
MessageBox.Show("NO TARGET FOUND.");
}
}
}
The thing is. initially, after the background worker finishes, I get the message box "NO TARGET FOUND.", however immediatley after, it would //Do Stuff Debugging shows that the RunWorkerCompleted event fires twice. This only happens on the first change to scanned value, all changes afterwards work as desired.
Questions:
1) Why does RunWorkerCompleted fire twice?
2) Why is the target not updated on the first fire of RunWorkerCompleted
You could try again with target being set in bw1_DoWork already, i.e.:
private void bw1_DoWork(object sender, DoWorkEventArgs e) {
target = new object(); // Query to database
}
private void bw1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if (ChangedScannedValue != null) {
ChangedScannedValue(_scannedValue);
}
}
Eventually you may want to replace the BackgroundWorker by a simpler solution with ThreadPool. I'd suggest this:
internal String ScannedValue {
get { return _scannedValue; }
set {
_scannedValue = value;
ThreadPool.QueueUserWorkItem( (WaitCallback) delegate {
target = new object(); // query database
if (ChangedScannedValue != null) ChangedScannedValue(_scannedValue);
} );
}
}

How can I run the event handler assigned to a mock?

I am trying to fire the event handler assigned to my timer mock. How can I test this private method here?
public interface ITimer
{
void Start();
double Interval { get; set; }
event ElapsedEventHandler Elapsed;
}
Client class assigns an event handler to this object. I want to test the logic in this class.
_timer.Elapsed += ResetExpiredCounters;
And the assigned method is private
private void ResetExpiredCounters(object sender, ElapsedEventArgs e)
{
// do something
}
I want to have this event handler in my mock and run it somehow. How can I do this?
Update:
I realized I was raising the event before I assigned the event handler. I corrected that but I still get this error:
System.ArgumentException : Object of type 'System.EventArgs' cannot be converted
to type 'System.Timers.ElapsedEventArgs'.
I raise it like this:
_timer.Raise(item => item.Elapsed += null, ElapsedEventArgs.Empty);
or
_timer.Raise(item => item.Elapsed += null, EventArgs.Empty);
Both won't work.
Update:
Here's the thing that worked for me. Note that it's not useful if you are trying to pass info to event handler like Jon pointed out in comments. I am just using it to mock the wrapper for System.Timers.Timer class.
_timer.Raise(item => item.Elapsed += null, new EventArgs() as ElapsedEventArgs);
In the end, this won't help at all if you need to use event arguments since it will be always null. However, it's the only way since ElapsedEventArgs has only an internal constructor.
ElapsedEventArgs has a private constructor and can not be instantiated.
If you use:
timer.Raise(item => item.Elapsed += null, new EventArgs() as ElapsedEventArgs);
Then the handler will recevie a null parameter and lose its SignalTime property:
private void WhenTimerElapsed(object sender, ElapsedEventArgs e)
{
// e is null.
}
You might want this parameter in some cases.
To solve this and make it more testable, I also created a wrapper for the ElapsedEventArgs, and made the interface use it:
public class TimeElapsedEventArgs : EventArgs
{
public DateTime SignalTime { get; private set; }
public TimeElapsedEventArgs() : this(DateTime.Now)
{
}
public TimeElapsedEventArgs(DateTime signalTime)
{
this.SignalTime = signalTime;
}
}
public interface IGenericTimer : IDisposable
{
double IntervalInMilliseconds { get; set; }
event EventHandler<TimerElapsedEventArgs> Elapsed;
void StartTimer();
void StopTimer();
}
The implementation will simply fire its own event getting the data from the real timer event:
public class TimerWrapper : IGenericTimer
{
private readonly System.Timers.Timer timer;
public event EventHandler<TimerElapsedEventArgs> Elapsed;
public TimeSpan Interval
{
get
{
return this.timer.Interval;
}
set
{
this.timer.Interval = value;
}
}
public TimerWrapper (TimeSpan interval)
{
this.timer = new System.Timers.Timer(interval.TotalMilliseconds) { Enabled = false };
this.timer.Elapsed += this.WhenTimerElapsed;
}
private void WhenTimerElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
{
var handler = this.Elapsed;
if (handler != null)
{
handler(this, new TimeElapsedEventArgs(elapsedEventArgs.SignalTime));
}
}
public void StartTimer()
{
this.timer.Start();
}
public void StopTimer()
{
this.timer.Stop();
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
this.timer.Elapsed -= this.WhenTimerElapsed;
this.timer.Dispose();
}
this.disposed = true;
}
}
}
Now, you can simplify and improve the mock of this event:
timer.Raise(item => item.Elapsed += null, new TimeElapsedEventArgs());
var yesterday = DateTime.Now.AddDays(-1);
timer.Raise(item => item.Elapsed += null, new TimeElapsedEventArgs(yesterday));
Less code to write, easier to work with and completely decoupled from the framework.
The Moq QuickStart guide has a section on events. I think you'd use
mock.Raise(m => m.Elapsed += null, new ElapsedEventArgs(...));
Dealt with this recently, you can construct an ElapsedEventArgs using reflection:
public ElapsedEventArgs CreateElapsedEventArgs(DateTime signalTime)
{
var e = FormatterServices.GetUninitializedObject(typeof(ElapsedEventArgs)) as ElapsedEventArgs;
if (e != null)
{
var fieldInfo = e.GetType().GetField("signalTime", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo != null)
{
fieldInfo.SetValue(e, signalTime);
}
}
return e;
}
This way you can continue using the original ElapsedEventHandler delegate
var yesterday = DateTime.Now.AddDays(-1);
timer.Raise(item => item.Elapsed += null, CreateElapsedEventArgs(yesterday));
Could do something like this to wrap your Timer
public class FakeTimer : IMyTimer
{
private event ElapsedEventHandler elaspedHandler;
private bool _enabled;
public void Dispose() => throw new NotImplementedException();
public FakeTimer(ElapsedEventHandler elapsedHandlerWhenTimeFinished, bool startImmediately)
{
this.elaspedHandler = elapsedHandlerWhenTimeFinished;
_enabled = startImmediately;
}
public void Start() => _enabled = true;
public void Stop() => _enabled = false;
public void Reset() => _enabled = true;
internal void TimeElapsed()
{
if (this._enabled)
elaspedHandler.Invoke(this, new EventArgs() as ElapsedEventArgs);
}
}

Event Bus implementation question

I'm trying to implement simple Event Bus
I started like this:
public class RegistrationData
{
public object RegisteredObject { get; set; }
public Type eventType { get; set; }
public EventHandler MethodToInvoke;
}
public class EventBus
{
private static EventBus instance;
private static readonly object lockObject = new object();
private static List<RegistrationData> registrationList;
private EventBus()
{
}
public static EventBus Instance
{
get
{
lock (lockObject)
{
registrationList = new List<RegistrationData>();
return instance ?? new EventBus();
}
}
}
public void Subscribe(RegistrationData registrationData)
{
if(!registrationList.Contains(registrationData)) registrationList.Add(registrationData);
}
public void Unsubscribe(object objectToUnregister, Type eventType)
{
foreach(RegistrationData data in registrationList)
if (data.RegisteredObject == objectToUnregister && data.eventType == eventType) registrationList.Remove(data);
}
public void UnregisterAllMessages(object objectToUnregister)
{
foreach(RegistrationData data in registrationList)
if(data.RegisteredObject == objectToUnregister) registrationList.Remove(data);
}
public void PublishEvent(object sender, EventArgs eventArgs)
{
foreach (RegistrationData data in registrationList)
if (EventArgs is typeof(data.Type)) data.MethodToInvoke(sender, eventArgs);
}
}
But I have problem in PublishEvent method. I'm unable to determine type of event argument.
And I'm suspicious that all this is pretty wrong.
Can someone point out what I do wrong, how should I implement this?
Or how event bus is generally implemented, or some framework which I can use instead of implementing my own and spending time on that.
Um, not really sure how your Eventbus should behave. Short of knowing where you are heading it can be useful to look at how other people implemented the problem.
There is a down-to-earth event aggregator in the caliburn.micro project
I like to use MemBus when I need an event aggregator, partly because I wrote it myself, partly because it covers all my needs in that respect. It is more involved than caliburn's one, but then it has more features
I think you should start by defining Event Bus. What do you see as the difference between an Event Bus and the built-in .NET mechanisms for firing and sinking events? What you have so far looks like it implements not much more than the equivalent of .NET events. .NET intrinsically supports event handling so you wouldn't need an event bus if you don't need more than what .NET already provides:
class Program
{
static void Main(string[] args)
{
BusinessObject1 bo = new BusinessObject1("First Value");
// Subscribe
bo.Publish += new BusinessObject.PublishObject(bo_Publish);
bo.Update("Second Value");
// UnSubscribe
bo.Publish -= new BusinessObject.PublishObject(bo_Publish);
bo.Update("Third Value");
// Subscribe multiple
bo.Publish += new BusinessObject.PublishObject(bo_Publish);
bo.Publish += new BusinessObject.PublishObject(bo_Publish2);
bo.Update("Fourth Value");
// UnregisterAllMessages
bo.UnsubcribeAll();
bo.Update("Fifth Value");
}
static void bo_Publish(BusinessObject sender, EventArgs args)
{
if (sender is BusinessObject1)
{
BusinessObject1 bo1 = (BusinessObject1)sender;
BusinessObject1.PublishBusinessObject1EventArgs args1 =
(BusinessObject1.PublishBusinessObject1EventArgs)args;
Console.WriteLine("Updated {0} to {1}", args1.oldValue, bo1.Value);
}
}
static void bo_Publish2(BusinessObject sender, EventArgs args)
{
if (sender is BusinessObject1)
{
BusinessObject1 bo1 = (BusinessObject1)sender;
BusinessObject1.PublishBusinessObject1EventArgs args1 =
(BusinessObject1.PublishBusinessObject1EventArgs)args;
Console.WriteLine("Second handler detected updated of {0} to {1}", args1.oldValue, bo1.Value);
}
}
}
abstract class BusinessObject
{
public delegate void PublishObject(BusinessObject sender, EventArgs args);
public event PublishObject Publish;
// PublishEvent
protected void Update(EventArgs args)
{
if (Publish != null)
Publish(this, args);
}
public void UnsubcribeAll()
{
Publish = null;
}
}
class BusinessObject1 : BusinessObject
{
public class PublishBusinessObject1EventArgs : EventArgs
{
public string oldValue;
public PublishBusinessObject1EventArgs(string oldValue)
{
this.oldValue = oldValue;
}
}
public delegate void PublishBusinessObject1(BusinessObject1 sender, PublishBusinessObject1EventArgs args);
public string Value {get; private set;}
public BusinessObject1(string value)
{
this.Value = value;
}
public void Update(string newValue)
{
PublishBusinessObject1EventArgs args = new PublishBusinessObject1EventArgs(Value);
Value = newValue;
base.Update(args);
}
}
Edit:
If you don't want your business objects to have to inherit from a common base class (as you suggested in your comment) you can make a few modifications so that EventBus stands more independently, but you still don't need to re-implement all the event registration framework to do this:
class Program
{
static void Main(string[] args)
{
BusinessObject1 bo = new BusinessObject1("First Value");
// Subscribe
EventBus.Publish += new EventBus.PublishObject(EventBus_Publish);
bo.Update("Second Value");
// UnSubscribe
EventBus.Publish -= new EventBus.PublishObject(EventBus_Publish);
bo.Update("Third Value");
// Subscribe multiple
EventBus.Publish += new EventBus.PublishObject(EventBus_Publish);
EventBus.Publish += new EventBus.PublishObject(EventBus_Publish2);
bo.Update("Fourth Value");
// UnregisterAllMessages
EventBus.UnsubcribeAll();
bo.Update("Fifth Value");
}
static void EventBus_Publish(object sender, EventArgs args)
{
if (sender is BusinessObject1)
{
BusinessObject1 bo1 = (BusinessObject1)sender;
BusinessObject1.PublishBusinessObject1EventArgs args1 =
(BusinessObject1.PublishBusinessObject1EventArgs)args;
Console.WriteLine("Updated {0} to {1}", args1.oldValue, bo1.Value);
}
}
static void EventBus_Publish2(object sender, EventArgs args)
{
if (sender is BusinessObject1)
{
BusinessObject1 bo1 = (BusinessObject1)sender;
BusinessObject1.PublishBusinessObject1EventArgs args1 =
(BusinessObject1.PublishBusinessObject1EventArgs)args;
Console.WriteLine("Second handler detected updated of {0} to {1}", args1.oldValue, bo1.Value);
}
}
}
static class EventBus
{
public delegate void PublishObject(object sender, EventArgs args);
public static event PublishObject Publish;
// PublishEvent
public static void Update(object sender, EventArgs args)
{
if (Publish != null)
Publish(sender, args);
}
public static void UnsubcribeAll()
{
Publish = null;
}
}
class BusinessObject1
{
public class PublishBusinessObject1EventArgs : EventArgs
{
public string oldValue;
public PublishBusinessObject1EventArgs(string oldValue)
{
this.oldValue = oldValue;
}
}
public delegate void PublishBusinessObject1(BusinessObject1 sender, PublishBusinessObject1EventArgs args);
public string Value { get; private set; }
public BusinessObject1(string value)
{
this.Value = value;
}
public void Update(string newValue)
{
PublishBusinessObject1EventArgs args = new PublishBusinessObject1EventArgs(Value);
Value = newValue;
EventBus.Update(this, args);
}
}
Edit 2: By the way, if you want more control over the subscription process, you can get more control there too by defining custom event accessors as described at http://msdn.microsoft.com/en-us/library/bb882534.aspx:
static class EventBus
{
public delegate void PublishObject(object sender, EventArgs args);
private static List<PublishObject> subscribers = new List<PublishObject>();
public static event PublishObject Publish
{
add
{
subscribers.Add(value);
Console.WriteLine("Added subscriber {0}.{1}", value.Method.DeclaringType.Name, value.Method.Name);
}
remove
{
bool result = subscribers.Remove(value);
Console.WriteLine("Removed subscriber {0}.{1} ({2})", value.Method.DeclaringType.Name, value.Method.Name, result ? "success" : "failure");
}
}
// PublishEvent
public static void Update(object sender, EventArgs args)
{
foreach (PublishObject p in subscribers)
{
Console.WriteLine("Publishing to {0}.{1}", p.Method.DeclaringType.Name, p.Method.Name);
p.Invoke(sender, args);
}
}
public static void UnsubcribeAll()
{
subscribers.Clear();
}
}
Well, as a first suggestion, it looks to me as if you're trying to implement this as a singleton. Otherwise, what would the
private static EventBus instance;
be good for? But the private instance member is never assigned anywhere, that's one thing I'd suggest you should fix. For reference, here's a really good article on various implementations of singletons. If you've got access to .net4 I'd suggest you use the LazySingleton3 approach.
The only other thing that comes to mind is, this looks like it could be a use-case for Generics. Have a look at the EventHandler<TEventArgs> Delegate.
Apart from that, I can't recommend much more since I don't exactly understand what you're trying to do.
EDIT
Have a look at the accepted answer on this question. It contains a link to a blog post of someone who implemented this several years ago. Seems like you don't need to re-invent the wheel.

Categories

Resources