I am working with timers and have implemented threading as first step in solving my problem. I have to send some reference every 30 seconds and this reference is created everytime a button is clicked. So I have the following code:
public MyReference SomeReference {get;set;}
public string MyFullName {get;set;} //this is bound to WPF textbox
public bool Saved()
{
SomeReference.Id = GeneratedId;
SomeReference.FullName = MyFullName;
return SavedtoDB(SomeReference);
}
public void OnButtonClick()
{
if(Saved()) //timer should only start if it is already saved in the database
var t = new Thread(() => ExecuteTimer(SomeReference));
}
public void ExecuteTimer(MyReference someReference)
{
System.Timers.Timer sendTimer = new System.Timers.Timer(30000);
sendTimer.Elapsed += (sender, e) => ExecuteElapsed(sender, e, someReference, sendTimer);
sendTimer.Start();
}
public void ExecuteElapsed(object source, ElapsedEventArgs e, MyReference someReference, System.Timers.Timer sendtimer)
{
sendtimer.Stop();
Send(someReference);
}
The following is the MyReference class:
public class MyReference()
{
public string Id {get;set;}
public string FullName {get;set;}
}
Edit for problem emphasis:
The problem is that it only sends the latest values someReference
and disregards the previous ones. How will I send each values after 30 seconds without replacing the them with the latest value of someReference?
It seems like you need a deep clone of your object.
Let me explain why a reference to your object is not enough.
The SomeReference
variable will always just point at a memory location where your MyReference
instance is located. If you click your button this data is written/overwritten. When your timers fires it will always load whatever data is located at SomeReference
and send it.
Implementing a deep copy will physically copy your instance in memory so you will keep a copy of the object which can be used to send without being overwritten from your Save()
call.
To implement this you can (there are a lot of other methods) use the ICloneable
interface like this:
class MyReference : ICloneable
{
public string Id { get; set; }
public string FullName { get; set; }
public object Clone()
{
return new MyReference()
{
Id = this.Id,
FullName = this.FullName
};
}
}
Now when clicking the button you can use Theodors Task.Delay
method and give it a copy of your object:
public void OnButtonClick()
{
//Here we now copy the complete object not just the reference to it
var localCopyOfTheReference = (MyReference)someReference.Clone();
var fireAndForget = Task.Run(async () =>
{
await Task.Delay(30000);
Send(localCopyOfTheReference);
});
}