How do I check an instance variable from a MVVM DispatchTimer class? - c#

So, I have this class for dealing with timers in MVVM:
class RecognitionProcessTimer
{
DispatcherTimer analysisProcessTimer;
public int Duration { get; set; }
public RecognitionProcessTimer()
{
this.Duration = 500;
}
public void StartTimer()
{
analysisProcessTimer = new DispatcherTimer();
analysisProcessTimer.Interval = TimeSpan.FromMilliseconds(this.Duration);
analysisProcessTimer.Tick += AnalysisProcessTimer_Tick;
analysisProcessTimer.Start();
}
public void StopTimer()
{
if (analysisProcessTimer != null)
{
analysisProcessTimer.Stop();
analysisProcessTimer = null;
}
}
private void AnalysisProcessTimer_Tick(object sender, object e)
{
analysisProcessTimer.Stop();
// C# code current object variables from the other class
}
}
So, I have an analysis class that will do analysis on every tick of the timer. The RecognitionProcessTimer will be initialized and Start() on this analysis class's code but the timer's AnalysisProcessTimer_Tick event needs to check and call some current analysis class object variables. How do I go on achieving this?
I've tried to initialize the analysis class on tick method but then I lose all the data on there as a new object is used instead of the using the object that initialize the RecognitionProcessTimer class.
TLDR: I'm trying to use the variables from the class that initialized RecognitionProcessTimer from RecognitionProcessTimer's tick method.
If the question seems unclear, then please let me know and I'll clarify further.
P.S: Can't use static variables.

Related

is there a better way to get information from another class?

I'm working on a program and I wanted to know the best way I can get information from one class to another.
My purpose is to get information from MyTimer to the Program class about how much "ticks" the timer did.
** I don't want from the class MyTimer to be dependent on the Program class (Like by using Program.SetUpdate()). MyTimer class should work with every class without changing his code.
I've already tried using public static method to send the information.
class Program
{
private static int _count;
private static MyTimer _myTimer;
static void Main(string[] args)
{
_count = 0;
_myTimer = new MyTimer() { Timer_Interval = 100 };
_myTimer.Start();
do
{
Console.WriteLine("Press q to quit.");
} while (Console.ReadKey().KeyChar.ToString().ToLower() != "q");
_myTimer.Stop();
}
public static void SetUpdate(int count)
{
_count = count;
Print();
}
private static void Print()
{
Console.WriteLine(_count);
}
}
class MyTimer
{
private Timer _timer;
private int _ticks;
public int Timer_Interval { get; set; }
public MyTimer()
{
_timer = new Timer();
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
}
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
Program.SetUpdate(_ticks);
_ticks++;
}
public void Start()
{
if (Timer_Interval == 0)
throw new InvalidOperationException("_timer interval can not be 0.");
_ticks = 0;
_timer.Interval = Timer_Interval;
_timer.Start();
}
public void Stop()
{
_timer.Stop();
}
}
The output is 1,2,3... until you press q/Q
I've tried to do it as simple as I can only to show you the concept.
So I created a class named Program that call MyTimer class.
MyTimer class is simply like a timer: stop,start and elapsed. Each interval it makes a "tick".
You'd normally fix this sort of issue by establishing a "direction". E.g. here it feels natural that it should be "from" Program "to" MyTimer. In that given direction, it's perfectly fine to make direct method calls, access properties, etc.
When you need information to flow in the other direction, that's when you use events. MyTimer raises an event and Program can have a handler. In this way, MyTimer doesn't know which classes are creating it/working with it or even how many event handlers have been installed.
I think Damien nailed it pretty much for this scenario.
Yet, I'd like to propose an alternative: Using a shared State Object.
You could define a State class, which does nothing else than hold the value of the tick-count.
You'd instanciate it in Program and pass it to the MyTimer. Mind that both classes now share the same instance (possibly introducing threading/concurrency issues if in multithreaded context).
MyTimer then would update the state on that shared Object.
Examples are Model/ViewModel classes in MVVM/WPF where you would bind some Control's property to that object's property.
Mind that Program wouldn't know of a occurring change out of the box. So that would have to be handled additionally. Either again via an Event, some "Observer Pattern" or similar.
As I said, events are the way to go here but I thought it couldn't hurt to suggest an alternative way of inter-class communication.

Working with multiple forms using c# in Visual Studio

I'm currently developing a Windows Form Application that uses two forms. I have no problems linking between the two forms. My issue is accessing a variable in Form2 that was created in Form1. How do you make a variable accessible to multiple forms in the same project?. I honestly tried to look for an answer, but could not find anything. Any help would be appreciated.
Here is the code for Form1:
namespace HourlyAlarm1
{
public partial class AlarmToneSetter : Form
{
public bool halfHourSelected;
public AlarmToneSetter()
{
InitializeComponent();
}
private void okButton_Click(object sender, EventArgs e)
{
if(halfHourRadio.Checked)
{
halfHourSelected = true;
}
else
{
halfHourSelected = false;
}
Form1 f1 = new Form1();
f1.ShowDialog();
}
public bool getHalfHourSelect()
{
return halfHourSelected;
}
}
}
Here is the code for Form2:
namespace HourlyAlarm1
{
public partial class Form1 : Form
{
int min;
System.Media.SoundPlayer sp;
public Form1()
{
InitializeComponent();
}
private void playSound()
{
sp = new System.Media.SoundPlayer(HourlyAlarm1.Properties.Resources.chipfork);
sp.Load();
sp.Play();
}
private void timer1_Tick(object sender, EventArgs e)
{
TimeLabel.Text = DateTime.Now.ToLongTimeString();
min = DateTime.Now.Minute;
if(HourlyAlarm1.AlarmToneSetter.g)
if(min == 0)
{
playSound();
}
}
}
}
If you want a variable which is accessible to any form within the project, mark it as static. That way you don't need a specific instance of the class that it's in to be able to access it.
You can use the forms Tag property if you want to pass just one variable.
Form1 f1 = new Form1();
f1.Tag="some value";
f1.ShowDialog();
and then in form 2 access it via it's own Tag property. Since it is stored as an object you will have to convert it to whatever datatype your application requires.
Example for getting the value in the new form:
string value = this.Tag.ToString();
As the question currently stands, it looks like you're trying to edit the halfHourSelected field in your AlarmToneSetter class from the Form1 class. To do that, there are several options:
Since this field is already public you can simply edit it like this (form Form1):
HourlyAlarm1.AlarmToneSetter.halfHourSelected = true;
or, if you plan on using it several times, add
using HourlyAlarm1;
/**
* declare the namespace, the class, etc.
*/
AlarmToneSetter.halfHourSelected = true
(Edit: As mentioned by Jason, this can be rewritten to be a property and comply with the style guide) However, since you already wrote a Java-style getter for this field, you should rewrite it in C# style; changing the declaration to
public bool HalfHourSelected{get;set;};
which will add the getter and setter for the property automatically.
Now, if you want to make this field persistent (that is, the configuration value should be saved across multiple executions of the program) then you should consider adding it to the settings of your project, and reference it like this
HourlyAlarm1.Properties.Settings.Default.halfHourSelected = true;
HourlyAlarm1.Properties.Settings.Default.Save();
or, as always, if you're gonna access them several times,
using HourlyAlarm1.Properties;
/**
* declare the namespace, the class, etc.
*/
Settings.Default.halfHourSelected = true;
Settings.Default.Save();
Yes, this is my first time answering a question in SO. If you have any recommendations, let me know in the comments! I'll appreciate the feedback.
Pass them as parameter of constructor. This way is used to set once time at creating an instance of class
public Form1(int i, string s, object o){}
Create public get/set. This way is used to set multiple times, but their value will be different among instances of class.
public int Price { get; set;}
Form1 frm1 = new Form1();
frm1.Price = 123;
Create public static field. This way is used to set multiple times, and it is same among instance of class.
public static int Price = 0;
Form1.Price = 123;
First of all public fields are discouraged in .NET: you should use properties.
Your problem is that bool is a value type and you can't "bind" it between forms, you need a reference type.
public class ReferenceBoolean
{
public bool Value{get;set;}
}
public class Form1
{
protected ReferenceBoolean HalfHourSelectedReference{get;set;}
public bool HalfHourSelected
{
get{return this.HalfHourSelectedReference.Value;}
set{this.HalfHourSelectedReference.Value = value;}
}
public Form1()
{
this.HalfHourSelectedReference = new ReferenceBoolean();
}
}
public class Form2
{
protected ReferenceBoolean HalfHourSelectedReference{get;set;}
public bool HalfHourSelected
{
get{return this.HalfHourSelectedReference.Value;}
set{this.HalfHourSelectedReference.Value = value;}
}
public Form2(ReferenceBoolean halfHourSelected)
{
this.HalfHourSelectedReference = value;
}
}
Now this might look all fine and dandy but there is one thing I did not do, because I'm not sure if you need it, if you update this value and have it bound to the UI in your form the update will not be reflected in the form. To do that you must implement something like the IPropertyNotificationChange pattern, which works much better in WPF.

Is it possible for instance to destroy/delete self?

NOTE: I'm interested in C#,Java and C++ most, but as this is the more academic question any language will do.
I know that this problem is solvable from outside, by using appropriate methods of given languages (calling free, Dispose, or by removing all references to instance).
My idea is that I create an instance, and in the constructor , I start the private timer. When the timer ends it will call some instance method and destroy the variable.
I think that in C# it should be possible to call Dispose on self, when the IDisposable is implemented, but this would not destroy the instace.
In C++ I could call the destructor, but that would lead to the memory leak, plus it is really bad practice.
In Java I have no clue, assigning to this it's not possible as it is final field.
So is there any way for instance, to destroy self?
Your question is very interesting, and I don't know of any other way to do so in C# but to force from the inside of the instance its destruction from the outside. So this is what I came up with to check if it is possible.
You can create the class Foo, which has event that is fired when the specific interval of the timer elapses. The class that is registered to that event (Bar) within event de-registers the event and sets the reference of the instance to null. This is how I would do it, tested and it works.
public class Foo
{
public delegate void SelfDestroyer(object sender, EventArgs ea);
public event SelfDestroyer DestroyMe;
Timer t;
public Foo()
{
t = new Timer();
t.Interval = 2000;
t.Tick += t_Tick;
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
OnDestroyMe();
}
public void OnDestroyMe()
{
SelfDestroyer temp = DestroyMe;
if (temp != null)
{
temp(this, new EventArgs());
}
}
}
public class Bar
{
Foo foo;
public Bar()
{
foo = new Foo();
foo.DestroyMe += foo_DestroyMe;
}
void foo_DestroyMe(object sender, EventArgs ea)
{
foo.DestroyMe -= foo_DestroyMe;
foo = null;
}
}
And in order to test this, you can set up a button click within a Form, something like this, and check it in the debugger:
Bar bar = null;
private void button2_Click(object sender, EventArgs e)
{
if(bar==null)
bar = new Bar();
}
So next time when you click the button, you will be able to see that Bar instance still exists but the Foo instance within it is null although it has been created within the Bar's constructor.
C++: If an object was allocated dynamically, it can delete its this pointer in its own function, provided the this pointer is never used again after that point.
No, there is no way to achieve what you are trying to do in C#.
If you consider an example :
public class Kamikadze {
......
private void TimerTick(..)
{
....
if(itsTime) {
DestroyMe();
}
}
.....
}
var kamikadze = new Kamikadze ();
after a while DestroyMe() will be called that cleans internal data.
But the reference kamikadze (pointer if you wish) is still valid and points to that memory location, so GC will not do anything, will not collect it, and instance of Kamikadze will remain in memory.
For C++ take a look at this:
http://www.parashift.com/c++-faq/delete-this.html
.
The closest thing in C# that I can think of:
On creation, every object stores a reference to itself in the GC root, e.g. by putting the reference into a class static list. Outside of the class, nobody is allowed to store (strong) references to the object. Everybody uses a WeakReference and checks if the Target is still IsAlive before touching the object. That way, the only thing that is keeping the object alive is the static reference.
When the object decides to kill itself, it simply removes the reference from the list. Sooner or later, the GC collects the object. Or, if you are really impatient, call GC.Collect() (ouch!).
But I really really would not recommend this solution!
It's much better put some flag into the class/object to signal whether it's still alive and make everybody check this flag before using the object. This can be combined with the IDisposable solution.
In C++, instances committing suicide are an integral part of the Finite State Machine Pattern:
//Context class contains a pointer to a State object.
void BattleshipGame::SetGameState(IState* state) {
game_state = state;
}
void BattleshipGame::Loss() {
game_state->Loss(this);
}
void BattleshipGame::Idle() {
game_state->Idle(this);
}
void BattleshipGame::FlyBy() {
game_state->FlyBy(this);
}
void BattleshipGame::Attack() {
game_state->Attack(this);
}
void BattleshipGame::Win() {
game_state->Win(this);
}
void BattleshipGame::Load() {
game_state->Loading(this);
}
//State base class contains methods for switching to every state.
class IState {
public:
virtual void Loading(BattleshipGame* context);
virtual void Idle(BattleshipGame* context);
virtual void FlyBy(BattleshipGame* context);
virtual void Attack(BattleshipGame* context);
virtual void Win(BattleshipGame* context);
virtual void Loss(BattleshipGame* context);
protected:
private:
};
//Implementations in the State base class are defined, but empty.
//Derived States only call what they need:
void StateIdle::Loss(BattleshipGame* context) {
//context->SetGameState(new StateLoss());
context->SetGameState(new StateLoss(context));
delete this;
}
void StateIdle::Idle(BattleshipGame* context) {
context->SetGameState(new StateIdle());
delete this;
}
void StateIdle::FlyBy(BattleshipGame* context) {
context->SetGameState(new StateFlyBy());
delete this;
}
void StateIdle::Win(BattleshipGame* context) {
context->SetGameState(new StateWin());
delete this;
}
//Similar design for all other states...
In C#, you're right you can implement IDisposable but the trick is instead of calling Dispose method make use of the using statement.
class Program
{
static void Main(string[] args)
{
using (MyClass obj = new MyClass())
{
obj.SayHello();
}
// obj.SayHello(); // Error: The name 'obj' does not exist in the current context
}
}
class MyClass : IDisposable
{
public void SayHello()
{
Console.WriteLine("Hello");
}
public void Dispose()
{
// Do something (e.g: close some open connection, etc)
}
}
For Reference: microsoft-docs/using-statement
I recommend using NFTLKEY. You can easily get it from the Nuget package. Best of all, it's open source: github project
Easier to understand than the examples here

Declare EventHandlers as Static or Non-Static in WPF Controls

I was working on creating a custom control with Command behavior and came across something odd. Some articles I found declared the CanExecuteChangedHandler EventHandler as static and others were non-static. Microsoft's SDK documentation shows static but when I declare it as static I get odd behavior when using multiple controls.
private static EventHandler canExecuteChangedHandler;
private void AddSecureCommand(ISecureCommand secureCommand)
{
canExecuteChangedHandler = new EventHandler(CanExecuteChanged);
securityTypeChangedHandler = new EventHandler(SecurityTypeChanged);
if (secureCommand != null)
{
secureCommand.CanExecuteChanged += canExecuteChangedHandler;
secureCommand.SecurityTypeChanged += securityTypeChangedHandler;
}
}
Does anyone know the proper way? Am I doing something wrong that is causing the static EventHandler not to work?
The stated reason for keeping a local copy of EventHandler is that the WPF commanding sub-system uses weak references internally and therefore we need to keep a reference to the specific delegate object that is added to the CanExecuteChanged event. If fact, anytime we are adding to any commanding sub-system event, we should also observe this practice, as you have for SecurityTypeChanged.
The short answer to your question is that canExecuteChangedHandler can be static, but you must be careful to only initialize it once. The reason it can be static is that all new EventHandler(CanExecuteChanged) will do the same thing if CanExecuteChanged is static. The reason to initialize it once is that different instances are different.
A private property that has the right read-only semantics is:
static EventHandler canExecuteChangedHandler
{
get
{
if (internalCanExecuteChangedHandler == null)
internalCanExecuteChangedHandler = new EventHandler(CanExecuteChanged);
return internalCanExecuteChangedHandler;
}
}
static EventHandler internalCanExecuteChangedHandler;
but this only works if CanExecuteChanged is static. If it is not, then remove the static qualifiers. In either case you have to be careful to actually use the property.
In this particular example, the second time that AddSecureCommand is called the first canExecuteChangedHandler is at risk of being garbage collected.
Finally, if this all sounds like black-magic, here is a code example to show what is happening.
public class Container
{
private WeakReference reference;
public object Object
{
get { return reference.IsAlive ? reference.Target : null; }
set { reference = new WeakReference(value); }
}
}
public class DelegateTest
{
private EventHandler eventHandler;
private Container container1;
private Container container2;
void MyEventHandler(object sender, EventArgs args)
{
}
public DelegateTest()
{
this.eventHandler = new EventHandler(MyEventHandler);
this.container1 = new Container { Object = this.eventHandler };
this.container2 = new Container { Object = new EventHandler(MyEventHandler) };
GC.Collect();
Console.WriteLine("container1: {0}", this.container1.Object == null);
Console.WriteLine("container2: {0}", this.container2.Object == null);
}
}
This produces this output:
container1: False
container2: True
which indicates that during the garbage collection that the second container had its EventHandler garbage-collected "out from underneath it". This is by design the way that weak references work and the explanation for you need to keep a reference to it yourself.

How to pass a reference into and out of a class

I would like to pass the reference of a variable into a class, use it and then get it out later.
Something like this:
// Create the comment Screen
string newCommentText = "";
commentsScreen = new CommentEntry(this, ref newCommentText);
commentScreen.ShowDialog();
...
_dataLayer.SaveOffComment(newCommentText);
And then in the comment class:
public partial class CommentEntry : Form
{
public CommentEntry(Control pControl, ref string commentResult)
{
InitializeComponent();
control = pControl;
// ***** Need a way for this to store the reference not the value. *****
_commentResult = commentResult;
}
private string _commentResult;
private void CommentEntry_Closing(object sender, CancelEventArgs e)
{
_commentResult = tbCommentText.Text.Trim();
}
}
Is there someway that newCommentText can have the value set in _commentResult in the closing method?
NOTE: Clearly it would be easy to just set a variable in my class and access it after the ShowDialog. This example is only a an approximation of my real issue and accessing any variables in the class after ShowDialog is done is not possible.
This will never work with a String as they are immutable and the variable will change to point to a new instance.
You have two basic options. The first is to simply have a getter for the result so it can be accessed when it is needed later. The other option is to have the owner pass in a delegate method that can be called passing in the resulting value. The owner would then receive the value when the CommentEntry is closing.
You generally can't directly store a 'reference to a reference' in C#, but you could do something like this:
public interface ICommented
{
string Comment { get; set; }
}
public class MyClass : ICommented
{
public string Comment { get; set; }
}
public partial class CommentEntry : Form
{
public CommentEntry(Control pControl, ICommented commented)
{
InitializeComponent();
control = pControl;
// ***** Need a way for this to store the reference not the value. *****
_commented = commented;
}
private ICommented _commented;
private void CommentEntry_Closing(object sender, CancelEventArgs e)
{
_commented.Comment = tbCommentText.Text.Trim();
}
}
So now your form can edit the comment of any class that has said it knows how to be commented upon.
As Dan Bryant pointed out, you cannot do that directly. One option is to wrap the reference into a class, but that requires writing a lot of boilerplate code. A simpler option is to use delegate and lambda functions (in C# 3.0) or anonymous delegates (C# 2.0):
string newCommentText = "";
// Using lambda that sets the value of (captured) variable
commentsScreen = new CommentEntry(this, newValue => {
newCommentText = newValue });
commentScreen.ShowDialog();
_dataLayer.SaveOffComment(newCommentText);
A modified version of the CommentEntry form would look like this:
public partial class CommentEntry : Form {
public CommentEntry(Control pControl, Action<string> reportResult) {
InitializeComponent();
control = pControl;
// Store the delegate in a local field (no problem here)
_reportResult = reportResult;
}
private Action<string> _reportResult;
private void CommentEntry_Closing(object sender, CancelEventArgs e) {
// Invoke the delegate to notify the caller about the value
_reportResult(tbCommentText.Text.Trim());
}
}
Make newComment property of CommentEntry class.
Here, try out what this guy is doing.
http://www.c-sharpcorner.com/UploadFile/gregory_popek/WritingUnsafeCode11102005040251AM/WritingUnsafeCode.aspx

Categories

Resources