Class in the BCL that will event at a given DateTime? - c#

Is there an object that will event at a given DateTime or DateTimeOffset? I am using a Timer to do this operation now but it requires a bit of calculation on my part, was just thinking there might already be something in place.

I don't see how you have to do any calculation:
public void StartTimer(DateTime target) {
double msec = (target - DateTime.Now).TotalMilliseconds;
if (msec <= 0 || msec > int.MaxValue) throw new ArgumentOutOfRangeException();
timer1.Interval = (int)msec;
timer1.Enabled = true;
}

I like:
System.Timers.Timer _WaitForScheduledTime;
_WaitForScheduledTime = new System.Timers.Timer();
_WaitForScheduledTime.Elapsed += new ElapsedEventHandler(WaitForScheduledTime_OnElapsed);
_WaitForScheduledTime.Interval = _ListOfJobs.IntervalUntilFirstJobIsToRun().TotalMilliseconds;
_WaitForScheduledTime.Start();
...
private void WaitForScheduledTime_OnElapsed(object source, EventArgs e)
{
log.Debug("Ready to run at least one job");
// restart the timer
_WaitForScheduledTime.Interval = _ListOfJobs.IntervalUntilFirstJobIsToRun().TotalMilliseconds;
_WaitForScheduledTime.Start();
}

If you are using ASP.NET you may be able to add an empty object into the Cache with a declared ExpirationDate then handle the CacheItemRemovedCallback. Just a thought, don't know if it will work for you.
If you not using ASP.NET you still may be able to use this trick with another caching framework such as the Enterprise Library Caching Block

Not that I know of. I rolled my own class to do that.

Related

Timer to control the bluetooth scan time

I'm currently working with a Bluetooth module, for which my application automatically scans in order auto-connect.
What i'm trying to achieve though, is to implement a restriction in terms of the amount of time that the application is allowed to scan for the module. I figured that it made good sense to use system.threading.Timer for this purpose, to run behind code.
if(c = 1)
{
bleText.Text = "Scanning...";
Scan_Function();
}
Private void Scan_Function()
{
//Timer stuff
}
However, i'm unaware if this is the correct way of doing it, and how i might be done.
You don't need a timer, just get the time when task starts and subtract it from the time it ends:
Private void Scan_Function()
{
DateTime start = DateTime.Now;
//Timer stuff
double milliSecondsElapsed = (DateTime.Now - start).TotalMilliSeconds;
}
Of course you can use these 2 lines outside the method too:
DateTime start = DateTime.Now;
Scan_Function()
double milliSecondsElapsed = (DateTime.Now - start).TotalMilliSeconds;

How to define a timers interval from a textbox in C#

I am learning C# and I am coding a simple auto typer, and I am trying to make it so users' can set their own interval. I tried using:
timer1.Interval = textbox1.Text;
but that doesn't seem to be working. I put that code in a button.. How do I get this to work? And why isn't it working?
You could use something like this:
int value;
// if it is really a value
if (int.TryParse(textbox1.Text, out value))
{
// if the value is not negativ (or you can enter the lower boundary here)
if (value > 0)
{
timer1.Interval = value;
}
}
As Steve mentioned in his comment, you need to connect a callback function to the timer1.Elapsed event (Attention: The name of the event differs depending on the timer you are using. It could also be timer1.Tick). You would do this by using the following code:
timer1.Elapsed += TimerElapsedCB;
and you need to define the callback function itself:
private void TimerElapsedCB(object sender, ElapsedEventArgs e)
{
// Do something here ;-)
// (e.g. access the signal time by using e.SignalTime)
}
try this :
Timer timer1 = new Timer();
timer1.Interval = int.Parse(textbox1.Text);
but keep in mind that user must enter a number , so you might need to handle the case when the user enter wrong data .
Edit :
You might use TryParse to make sure it's a number :
int myInt = 0;
Timer timer1 = new Timer();
bool parsed = int.TryParse(textbox1.Text,out myInt);
if (parsed)
{
timer1.Interval = myInt;
}

How to using Timer in c# to hovering button?

I want to make hovering button in my game. Because when my cursor touch the button it will go to another screen immediately. I don't like this so much. I use xna 4.0 with visual studio 2010 to make this project. (use kinect without wpf)
How to use timer in this case ? Please help me
if (Hand.contian(Button) && holdtime == targetHoldtime)
{
}
You have to manage time by yourself based in elapsed time per frame:
ft = GameTime.Elapsed.TotalSeconds; // Xna
ft= 1/30f; // 30fps
And can be done in similar way to this:
class Button {
public float Duration = 1; // One second
public Rectangle Bounds; // Button boundaries
public float Progress { get{ return Elapsed/Duration; } }
float Elapsed = 0;
public void Update(float ft) {
if (Bounds.Contains( HandPosition ))
{
if (Elapsed<Duration) {
Elapsed += ft;
if (Elapsed>Duration) {
Elapsed = Duration;
OnClick();
}
}
} else {
Elapsed = 0;
}
}
}
I would first suggest that you look through the SDK documentation and the built in KinectInteraction controls. They may provide you with what you are looking for. Most notably SDK 1.7 removed that "HoverDwell" button in favor of a "press" action, which is a more natural interaction in a gesture system. You may want to look at using that motion instead.
If you truly desire a "click on hover" type action, you can look at the code in SDK 1.6 for an example. Several examples are available online at the Kinect for Windows CodePlex repository. The specific control example you are looking for is in the "BasicInteraction-WPF" project, and is called HoverDwellButton.
The "button" is actually a ContentControl which means you can place any content in there to make it a button. It can be a simple image, or a complex Grid. It has all the hooks to fire events when the timer on your hover goes off.
There is a decent amount of complexity in this control, which is what makes it work for a wide range of applications. At the core of the interaction is a simple DispatcherTimer.
private void OnPreviewHandEnter(object sender, HandInputEventArgs args)
{
if (this.trackedHandHovers.FirstOrDefault(t => t.Hand.Equals(args.Hand)) == null)
{
// additional logic removed for answer sanity
var timer = new HandHoverTimer(DispatcherPriority.Normal, this.Dispatcher);
timer.Hand = args.Hand;
timer.Interval = TimeSpan.FromMilliseconds(Settings.Default.SelectionTime);
timer.Tick += (o, s) => { this.InvokeHoverClick(args.Hand); };
this.trackedHandHovers.Add(timer);
timer.Start();
}
args.Handled = true;
}
Notice that the Tick event is calling InvokeHoverClick, which (in part) reads as follows:
public void InvokeHoverClick(HandPosition hand)
{
// additional logic removed for answer sanity
var t = new DispatcherTimer();
t.Interval = TimeSpan.FromSeconds(0.6);
t.Tick += (o, s) =>
{
t.Stop();
var clickArgs = new HandInputEventArgs(HoverClickEvent, this, hand);
this.RaiseEvent(clickArgs);
this.IsSelected = false;
};
t.Start();
}
This now fires an event after a set amount of time. This event can be capture and acted upon to your liking.
Again, I first recommend looking at the newer interactions in SDK 1.7. If you still want a timed hover click action, check out the links above. I used the HoverDwellButton to great effect in several different areas.

How to Bench mark code using .Net Framework 4 on Desktop application

I have written my Desktop application but it's a little slow at times so I am trying to Optimize it as much as possible. Trouble is I don't know how.
Here is the code I have questions about
if (((mainRibbonForm)Parent.Parent.Parent.Parent.Parent.Parent.Parent)).myParentScopeVar == false)
{
//something goes here
}
//VS
if (myLocalScopeVar == false)
{
//something goes here
}
All the objects are created in mainRibbonForm and assigned, It seems that I can't call something like this.
mainRibbonForm.myparentScopeVar == false
So while in the last object, I just walked backwards to grab the variable using the Parent command variable.
I am not sure if I should always look at the parent scope for the variable or assign the variable to the last control as a localscope and only update it when the parent scope variable changes, which is not very often, but it does change.
I have some of these in timers and peppered every where in the code.. I am very new to C# and I translated everything from VB.Net to C# I am just trying to learn the correct or the best practices of programming in C#
Which is Faster and uses less resources?
How to I benchmark on my own next time?
I think that this code is overkill and horrible to see:
if (((mainRibbonForm)Parent.Parent.Parent.Parent.Parent.Parent.Parent)).myParentScopeVar == false)
{
//something goes here
}
Instead of this I prefer use a static variable and then call it using mainRibbonForm.myParentScopeVar. So you could insert this in your class:
public static bool myParentScopeVar;
Or you can pass this boolean through the constructors.
If you want to do a benchmark use the Stopwatch class that is a high resolution timer to measure how long your code will run and loop the code that you are testing more times to get a medium time that includes his best and worst performances:
Stopwatch timer = new Stopwatch();
timer.Start();
for(int i = 0; i < 1000; i++)
{
if (((mainRibbonForm)Parent.Parent.Parent.Parent.Parent.Parent.Parent)).myParentScopeVar == false)
{
//something goes here
}
}
timer.Stop();
TimeSpan timespan = timer.Elapsed;
MessageBox.Show(String.Format("{0:00}:{1:00}:{2:00}", timespan.Minutes, timespan.Seconds, timespan.Milliseconds / 10));
timer.Restart();
for(int i = 0; i < 1000; i++)
{
if (myLocalScopeVar == false)
{
//something goes here
}
}
timer.Stop();
TimeSpan timespan = timer.Elapsed;
MessageBox.Show(String.Format("{0:00}:{1:00}:{2:00}", timespan.Minutes, timespan.Seconds, timespan.Milliseconds / 10));
I think that my solution and your second solution using myLocalScopeVar are more efficient.

Providing multiple instances of a form yet processing events one at a time

I need to be able to let multiple instances of the same form be open as my application can be used in different places at once. On the other hand I need to be able to process the operations during the "OK" event one at a time to ensure data is stored safely and not overwritten by another form instance by accident.
I show my form using the .Show() method as I am using a few delegates in it:
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
bookingForm = new BookingForm(AddMemberBooking, AddUserBooking, CloseBooking);
bookingForm.Show();
}
I have tried to use the mutex to allow only one event of the OK button being pressed happen at a time, i have combined this with a Thread to meet the criteria i need.
When i click on the "OK" button I am given the following error:
Cross-thread operation not valid: Control 'comboBoxDay' accessed from a thread other than the thread it was created on.
This is the code for my booking form class:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Collection
{
//Allows the class to be serialized
[Serializable()]
public delegate void AddMemberBookingMethod(int date, int time, int mNo);
public delegate void AddUserBookingMethod(int date, int time, string fName, string lName, string pCode);
public delegate void CloseBookingFormMethod();
public partial class BookingForm : Form
{
public CloseBookingFormMethod CloseBookingForm;
public AddMemberBookingMethod AddMemberBooking;
public AddUserBookingMethod AddUserBooking;
private Mutex bookingMut = new Mutex();
private Thread thread;
public bool IsUser;
public BookingForm(AddMemberBookingMethod ambm, AddUserBookingMethod aubm, CloseBookingFormMethod cbfm)
{
InitializeComponent();
AddMemberBooking = ambm;
AddUserBooking = aubm;
CloseBookingForm = cbfm;
checkBoxMember.Checked = true;
//Control.CheckForIllegalCrossThreadCalls = false;
}
private void checkBoxUser_CheckedChanged(object sender, EventArgs e)
{
if (checkBoxUser.Checked)
{
IsUser = true;
checkBoxMember.CheckState = CheckState.Unchecked;
textBoxMNo.Enabled = false;
textBoxFName.Enabled = true;
textBoxLName.Enabled = true;
textBoxPCode.Enabled = true;
}
else
{
IsUser = false;
checkBoxMember.CheckState = CheckState.Checked;
textBoxMNo.Enabled = true;
textBoxFName.Enabled = false;
textBoxLName.Enabled = false;
textBoxPCode.Enabled = false;
}
}
private void checkBoxMember_CheckedChanged(object sender, EventArgs e)
{
if (checkBoxMember.Checked)
{
IsUser = false;
checkBoxUser.CheckState = CheckState.Unchecked;
textBoxFName.Enabled = false;
textBoxLName.Enabled = false;
textBoxPCode.Enabled = false;
}
else
{
IsUser = true;
checkBoxUser.CheckState = CheckState.Checked;
textBoxMNo.Enabled = false;
textBoxFName.Enabled = true;
textBoxLName.Enabled = true;
textBoxPCode.Enabled = true;
}
}
private void buttonOK_Click(object sender, EventArgs e)
{
this.thread = new Thread(new ThreadStart(MakeBooking));
this.thread.Name = "bookingThread";
this.thread.Start();
}
private void MakeBooking()
{
this.bookingMut.WaitOne();
int date = this.comboBoxDay.SelectedIndex;
int time = this.comboBoxTime.SelectedIndex;
if (IsUser)
{
string fName = textBoxFName.Text;
string lName = textBoxLName.Text;
string pCode = textBoxPCode.Text;
AddUserBooking(date, time, fName, lName, pCode);
}
else
{
int mNo = int.Parse(textBoxMNo.Text);
AddMemberBooking(date, time, mNo);
}
this.bookingMut.ReleaseMutex();
CloseBookingForm();
}
private void buttonClose_Click(object sender, EventArgs e)
{
CloseBookingForm();
}
}
}
I realise I may not be doing this in the most efficient way but time is a bit of a factor.
I've researched the error and have heard of using delegates and .Invoke() but I'm still not entirely sure how to fix it.
EDIT:
I've found this code snippet when searching for a fix to my problem. I don't understand where/how I would use it.
if(this.InvokeRequired)
{
this.Invoke(new MyEventHandler(this.CreateAForm()));
return;
}
EDIT2:
Seems the guy finally saw sense, by creating the from with the new word it apparently passes the criteria. I wish I'd have known this before trying to reinvent the wheel.
You are getting this exception because your thread is accessing controls. That's not legal, control properties must only ever be accessed from the UI thread. You're okay on the TextBox.Text property, that one happens to be cached. But not ComboBox.SelectedIndex. And closing the form from another thread is going to bomb too.
Your mutex has nothing to do with it, but keep it if you want to prevent threads from overlapping. Using a delegate's Invoke method isn't going to solve it, that just starts a thread as well. You'll need to collect the info that the thread is going to need in a little helper class and pass that as the argument to the Thread.Start() method.
Closing the form is a bit tricky too, the user might well have already closed it while the thread was running. That's going to cause an ObjectDisposed exception. A quick fix is to set the form's Enabled property to false so the user can't close it. You'll need to use the form's Invoke() method to ensure the closing is done on the UI thread.
Last but not least, if these threads don't take a lot of time (a second or so), consider not using threads at all and display a wait cursor instead.
One simple way to do this is to use the overload of the Thread.Start method that accepts an object: Thread.Start Method (Object). In this object you will store all the data/state necessary in order to make the update.
All the code that references the form and its controls needs to be moved into the OK click event method or refactored out to a method that just returns a data object. Then pass this object into the thread start method.
Some pseudo code:
on_click_event()
{
object data=getFormData();
thread.start(data);
}
There are better ways to do this but this is a quick fix for your code.
I think you could simply disable the OK buttons on other open forms to give users a visual cue. Then you shouldn't even have the issue. Provide a callback delegate to something in the application controller which knows which forms are open. Each form can provide a public method to disable the OK button. Disable to OK button on all the other forms.
I'm not really following your code too well. I would think the mutex could be outside of the form code in the first place (i.e. in the delegates that do the actual work), and if it is within a single application, you could just use the lock (object) method to ensure only one thread is executing a given bit of code.
I'd also like to add that a mutex is not going to stop multiple users on different machiens being able to click OK at the same time. I'm not sure if that's what you meant in your question by a form being run in different places.
I think that AddUserBooking and the other delegate should be responsible for ensuring that they are threadsafe and this should not be part of the UI. If they aren't threadsafe, why aren't they? It's relatively easy to make database commit functions each have their own connection to the database during their operations and thread-safety should not be an issue.

Categories

Resources