Change Timer interval value on the fly - c#

I have a CSV file that will read LineByLine ... like :
0
2.25
5
5.30
I need to Timer interval to change ... but there is no effect when its changed...
I need to fill a textbox.
please let me know your solution
while ((currentLine = sr.ReadLine()) != null)
{
string[] temp = currentLine.Split(',');
timerinterval = (int)(Convert.ToDouble(temp[0])*1000);
if ((int)(Convert.ToDouble(temp[0]) * 1000) != 0)
{
mytimer.Stop();
mytimer.Interval = (int)(Convert.ToDouble(temp[0]) * 1000);
mytimer.Start();
txtCurrentLine.Text = currentLine;
txtTime.Text = timerinterval.ToString();
}
}

public TimeCapture
{
public TimeCapture() => Start = DateTime.Now;
public Start { get; }
public TimeSpan Duration => DateTime.Now.Subtract(Start).Value.TotalSeconds;
}
Then when you intend to read each line.
var timer = new TimeCapture();
while(...)
{
...
txtTime.Text = timer.Duration;
}
Now as you iterate every single line you're capturing the duration as it is reading each line. If you are interested in line by line duration, simply create a new object per line, then put duration and it'll be for the linear code block.

Related

How to get Timespan in Milliseconds

I want to get the timespan in milliseconds by comparing two timestamps with DateTime.Now and the previous DateTime. I want to check if there is an event every 10 Milliseconds or later but the totalmilliseconds from DeltaT is like 188 or so. It is too high than I am expecting that is why I think there must be somethimg wrong. Or does everything look alright?
DateTime timestamp;
DateTime timestampAlt;
TimeSpan deltaT;
public void OnSensorChanged(SensorEvent e)
{
timestamp = System.DateTime.Now;
deltaT = timestamp - timestampAlt;
if (deltaT.TotalSeconds <= 0.01)
{
return;
}
UPDATE:
I really appreciate all of you answers but I think there is a misunderstanding (my mistake sry). So here again:
Whenever the listener recognizes an event, I want to save the timestamp and compare with the timespamp of the event before. If there is a gap of more than 10 Milliseconds between the 2 events, then I do want to know more about this new event. If not, I dont even want to continue and will leave by a return.
public void OnSensorChanged(SensorEvent e)
{
timestamp = System.DateTime.Now;
deltaT = timestamp - timestampAlt;
//int deltaT2 = timestamp.Millisecond - timestampAlt.Millisecond;
String timestampStr = timestamp.ToString("ff");
String timestampStrA = timestampAlt.ToString("ff");
if (deltaT.TotalMilliseconds <= 10 || deltaT.TotalMilliseconds <= -10) //deltaT.Seconds <= 0.01
{
return;
}
timestampAlt = timestamp;
newValue = e.Values[2];
//if (buffer[99] != 0.00)
// if last element of list is empty, add elements to buffer
if (buffer.Count <=99)
{
buffer.Add(newValue);
zeitbuffer.Add(timestamp);
}
else
{
Ableitung(DeltaBuffer(), DeltaTime()); // if last index of list is filled, do that function
}
if (e.Values[2] >= 11)
{
try
{
lock (_syncLock)
{
String z2 = newValue.ToString("0.0");
//noteInt2 = Convert.ToInt32(newValue);
try
{
_sensorTextView2.Text = string.Format("Note: {0}", z2 );
eventcounter.Add(z2);
You can use deltaT.TotalMilliseconds which expresses your delta in milliseconds. Therefore your check could be rewritten as
if (deltaT.TotalMilliseconds <= 10)
{
return;
}
10 is a value I inferred. It might not be what you need, but your question is partial. This answer addresses your particular question, however if you need to measure the duration of a task you should use the Stopwatch class, which is designed for that purpose.
if you want to fire an event every n-Seconds you can use a timer that fires an event when he elapses:
Timer timer = new Timer();
timer.Interval = 100;
timer.Elapsed += YourAmasingEvent;
timer.Start();
private void YourAmasingEvent(object sender, ElapsedEventArgs e)
{
//do something here
(sender as Timer).Start();
}
Using your code:
I guess you want to wait until the time elapsed in this case you would have to use a loop like this:
timestamp = System.DateTime.Now;
deltaT = timestamp - timestampAlt;
while(true)
{
if (deltaT.TotalSeconds <= 0.01)
{
return;
}
timestamp = System.DateTime.Now;
deltaT = timestamp - timestampAlt;
}

Show subtitles in WPF

I'm developing an application in which I have a window with a MediaElement. The user can play the movie in this window. I would like to add an option to play the movie with subtitles. I know how to display text over the MediaElement but the problem is, how to display subtitles at certain intervals.
My solution (which doesn't work): I will parse a .src file to a dictionary where Key is start time and value is text.
Next, I have a timer with a 1 ms interval and at each interval I would check if the movie-time exists in the dictionary. If yes, I will show the value. Problem is, that I'm not able to check dictionary every millisecond but the interval is about 20 ms and this is the problem. So do you know how to call it every 1 millisecond?
private void timer_Tick(object sender, EventArgs e)
{
string text = MediaElement.Position.ToString("HH:mm:ss.fff");
Thread t = new Thread(() => SearchThread(text));
t.Start();
if (MediaElement.NaturalDuration.HasTimeSpan)
timer.Text = String.Format("{0} / {1}", MediaElement.Position,
MediaElement.NaturalDuration.TimeSpan.ToString());
}
private void SearchThread(string pos)
{
string text = srcFileControler.Get(pos); //take value from dictionary if exist
if (text != "")
this.txtSub.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() => { txtSub.Text = text; }));
}
I'd recommend a more reusable approach that let's you seek, skip and replay. Since a lot of your code is missing in the question I've made a couple of assumptions of what it might look like.
Keep your subtitles in a simple class that contains at least a timestamp at which it should appear and the text to display. If at any time you want to display no text at all, simply add an entry with String.Empty for the Text.
public class SubtitleEntry
{
public TimeSpan TimeStamp { get; set; }
public string Text { get; set; }
}
To keep track of which position (timestamp and subtitle-index) you are, check if the next entry's timestamp is earlier than the last known timestamp. If the "current" subtitle entry has changed, raise an event to update the text.
public class SubtitleManager
{
public event EventHandler<string> UpdateSubtitles;
private List<SubtitleEntry> _entries;
private int _currentIndex = -1;
private TimeSpan _currentTimeStamp = TimeSpan.MinValue;
public SubtitleManager()
{
_entries = new List<SubtitleEntry>();
}
public void SetEntries(IEnumerable<SubtitleEntry> entries)
{
// Set entries and reset previous "last" entry
_entries = new List<SubtitleEntry>(entries);
_currentTimeStamp = TimeSpan.MinValue;
_currentIndex = -1;
}
public void UpdateTime(TimeSpan timestamp)
{
// If there are no entries, there is nothing to do
if (_entries == null || _entries.Count == 0)
return;
// Remember position of last displayed subtitle entry
int previousIndex = _currentIndex;
// User must have skipped backwards, re-find "current" entry
if (timestamp < _currentTimeStamp)
_currentIndex = FindPreviousEntry(timestamp);
// Remember current timestamp
_currentTimeStamp = timestamp;
// First entry not hit yet
if (_currentIndex < 0 && timestamp < _entries[0].TimeStamp)
return;
// Try to find a later entry than the current to be displayed
while (_currentIndex + 1 < _entries.Count && _entries[_currentIndex + 1].TimeStamp < timestamp)
{
_currentIndex++;
}
// Has the current entry changed? Notify!
if(_currentIndex >= 0 && _currentIndex < _entries.Count && _currentIndex != previousIndex)
OnUpdateSubtitles(_entries[_currentIndex].Text);
}
private int FindPreviousEntry(TimeSpan timestamp)
{
// Look for the last entry that is "earlier" than the specified timestamp
for (int i = _entries.Count - 1; i >= 0; i--)
{
if (_entries[i].TimeStamp < timestamp)
return i;
}
return -1;
}
protected virtual void OnUpdateSubtitles(string e)
{
UpdateSubtitles?.Invoke(this, e);
}
}
In your window, that would look something like this:
private DispatcherTimer _timer;
private SubtitleManager _manager;
public MainWindow()
{
InitializeComponent();
_manager = new SubtitleManager();
_manager.SetEntries(new List<SubtitleEntry>()
{
new SubtitleEntry{Text = "1s", TimeStamp = TimeSpan.FromSeconds(1)},
new SubtitleEntry{Text = "2s", TimeStamp = TimeSpan.FromSeconds(2)},
new SubtitleEntry{Text = "4s", TimeStamp = TimeSpan.FromSeconds(4)},
new SubtitleEntry{Text = "10s", TimeStamp = TimeSpan.FromSeconds(10)},
new SubtitleEntry{Text = "12s", TimeStamp = TimeSpan.FromSeconds(12)},
});
_manager.UpdateSubtitles += ManagerOnUpdateSubtitles;
}
private void ManagerOnUpdateSubtitles(object sender, string text)
{
txtSubtitle.Text = text;
}
private void BtnLoadVideo_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
if (dialog.ShowDialog(this) != true) return;
element.Source = new Uri(dialog.FileName, UriKind.Absolute);
_timer = new DispatcherTimer();
_timer.Tick += Timer_Tick;
_timer.Interval = new TimeSpan(0,0,0,0,50); //50 ms is fast enough
_timer.Start();
}
private void Timer_Tick(object sender, EventArgs eventArgs)
{
_manager.UpdateTime(element.Position);
}
I would go with an approach similar to Evk's solution but slightly different.
From an ordered list of subtitle (by time of appearance):
Take the first subtitle
Compute the remaining timespan before its moment of showing
Wait for that duration
Finally display it
Take the next subtitle, and repeat.
Here is a code using .NET async/await and Task.
public class Subtitle
{
/// <summary>
/// Gets the absolute (in the movie timespan) moment where the subtitle must be displayed.
/// </summary>
public TimeSpan Moment { get; set; }
/// <summary>
/// Gets the text of the subtitle.
/// </summary>
public string Text { get; set; }
}
public class SubtitleManager
{
/// <summary>
/// Starts a task that display the specified subtitles at the right moment, considering the movie playing start date.
/// </summary>
/// <param name="movieStartDate"></param>
/// <param name="subtitles"></param>
/// <returns></returns>
public Task ProgramSubtitles(DateTime movieStartDate, IEnumerable<Subtitle> subtitles)
{
return Task.Run(async () =>
{
foreach (var subtitle in subtitles.OrderBy(s => s.Moment))
{
// Computes for each subtitle the time to sleep from the current DateTime.Now to avoid shifting due to the duration of the subtitle display for example
var sleep = DateTime.Now - (movieStartDate + subtitle.Moment);
// Waits for the right moment to display the subtitle
await Task.Delay(sleep);
// Show the subtitle
this.ShowText(subtitle.Text);
}
});
}
private void ShowText(string text)
{
// Do your stuff here
// Since the calling thread is not the UI thread, you will probably need to call the text display in the dispatcher thread
}
}
You could add some other stuff like:
If the moment is past, do nothing and take the next subtitle
You could use a shared Timespan variable to manually shift all the subtitle moment of apparition (if the subtitles are not synchronized with the movie)
Do not run the Task in the ProgramSubtitles function but let the caller run the function in a Task? (Depending on your needs)
I'd say it's better to take another approach. When movie starts - grab first subtitle interval from the list (say it's 00:01:00) and start timer which will fire after this time. Then when this timer fires all you need is just show corresponding subtitle and repeat by grabbing next interval time and starting timer again. Some sketch code:
// assuming queue is "sorted" by interval
private readonly Queue<Tuple<TimeSpan, string>> _subtitles = new Queue<Tuple<TimeSpan, string>>();
// call this once, when your movie starts playing
private void CreateTimer() {
var next = _subtitles.Dequeue();
if (next == null) {
ShowText(null);
return;
}
System.Threading.Timer timer = null;
timer = new System.Threading.Timer(_ => {
timer.Dispose();
ShowText(next.Item2);
CreateTimer();
}, null, next.Item1, Timeout.InfiniteTimeSpan);
}
private void ShowText(string text) {
Dispatcher.Invoke(() =>
{
// show text
});
}

How to create an advanced countdown timer

Well, this question is related to this one, so you guys can understand it better
How to convert the "time" from DateTime into int?
My Answer to it:
txtAtiv.Text = dataGridView1.Rows[0].Cells[1].Value + "";
string value = dataGridView1.Rows[0].Cells[2].Value + "";
lblLeft.Text = value.Split(' ')[1];
textStatus.Text = "";
DateTime timeConvert;
DateTime.TryParse(value, out timeConvert);
double time;
time = timeConvert.TimeOfDay.TotalMilliseconds;
var timeSpan = TimeSpan.FromMilliseconds(time);
lblSoma.Text = timeSpan.ToString();
timer2.Start();
According to the answer I wrote right there, I want to know if there's a way I can apply it to a timer and do the DataGrid values (converted) turn into a timer value. So if I press a button they start the countdown.
I have tried to insert this code inside the timer:
private void timer2_Tick(object sender, EventArgs e)
{
string timeOp = dataGridView1.Rows[0].Cells[2].Value + "";
DateTime timeConvert;
DateTime dateTime = DateTime.Now;
DateTime.TryParse(timeOp, out timeConvert);
double time;
time = timeConvert.TimeOfDay.TotalMilliseconds;
var timeSpan = TimeSpan.FromMilliseconds(time);
if (time > 0)
{
time = time - 1000; //(millisec)
lblCountdown.text = time.ToString();
}
}
didn't count down or anything, does someone has an idea of what should I do or why it isn't working?
The value of time never changes, because you create it again fresh each time.
To solve this, you have to declare the variable you decrement outside of the Tick event.
Put these two variables on your form:
private int milliSecondsLeft = 0;
private bool timeSet = false;
Then change the 'tick' event to this:
private void timer2_Tick(object sender, EventArgs e)
{
if (!timeSet) // only get the value once
{
string dateTimeFromGrid = "4/29/2016 5:00:00 AM"; //hardcoded for simplicity, get the string from your grid
DateTime fromGrid;
DateTime.TryParse(dateTimeFromGrid, out fromGrid);
milliSecondsLeft = (int)fromGrid.TimeOfDay.TotalMilliseconds;
timeSet = true;
}
milliSecondsLeft = milliSecondsLeft - 100; // timer's default Interval is 100 milliseconds
if (milliSecondsLeft > 0)
{
var span = new TimeSpan(0, 0, 0, 0, milliSecondsLeft);
lblCountdown.Text = span.ToString(#"hh\:mm\:ss");
}
else
{
timer2.Stop();
}
}
Make sure

Only execute method after X number of seconds since last use

I have a foreach statement, and I need to make it so that a method called at the end of the foreach and if statements only executes after 3 seconds from it's last execution time.
Here's the code.
//Go over Array for each id in allItems
foreach (int id in allItems)
{
if (offered > 0 && itemsAdded != (offered * 3) && tDown)
{
List<Inventory.Item> items = Trade.MyInventory.GetItemsByDefindex(id);
foreach (Inventory.Item item in items)
{
if (!Trade.myOfferedItems.ContainsValue(item.Id))
{
//Code to only execute if x seconds have passed since it last executed.
if (Trade.AddItem(item.Id))
{
itemsAdded++;
break;
}
//end code delay execution
}
}
}
}
And I don't want to Sleep it, since when an item is added, I need to get confirmation from the server that the item has been added.
How about a simple time comparison?
var lastExecution = DateTime.Now;
if((DateTime.Now - lastExecution).TotalSeconds >= 3)
...
You could save 'lastExecution' in your Trade-Class. Of course, the code block is not called (items are not added) with this solution if the 3 seconds haven't elapsed.
--//---------------------------------
Different solution with a timer: we add programmatically a Windows Forms timer component. But you will end in Programmers Hell if you use this solution ;-)
//declare the timer
private static System.Windows.Forms.Timer tmr = new System.Windows.Forms.Timer();
//adds the event and event handler (=the method that will be called)
//call this line only call once
tmr.Tick += new EventHandler(TimerEventProcessor);
//call the following line once (unless you want to change the time)
tmr.Interval = 3000; //sets timer to 3000 milliseconds = 3 seconds
//call this line every time you need a 'timeout'
tmr.Start(); //start timer
//called by timer
private static void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
Console.WriteLine("3 seconds elapsed. disabling timer");
tmr.Stop(); //disable timer
}
DateTime? lastCallDate = null;
foreach (int id in allItems)
{
if (offered > 0 && itemsAdded != (offered * 3) && tDown)
{
List<Inventory.Item> items = Trade.MyInventory.GetItemsByDefindex(id);
foreach (Inventory.Item item in items)
{
if (!Trade.myOfferedItems.ContainsValue(item.Id))
{
//execute if 3 seconds have passed since it last execution...
bool wasExecuted = false;
while (!wasExecuted)
{
if (lastCallDate == null || lastCallDate.Value.AddSeconds(3) < DateTime.Now)
{
lastCallDate = DateTime.Now;
if (Trade.AddItem(item.Id))
{
itemsAdded++;
break;
}
wasExecuted = true;
}
System.Threading.Thread.Sleep(100);
}
}
}
}
}

In my numericUpDown Changed event im calling a function() and when im changing the numeric value when program is running its getting slower

This is the numeric changed event code with timer2 wich didnt solve hte problem the function im calling is DoThresholdCheck()
The problem is that in this function im creating each time im changing the numeric value a temp list each time im moving the numeric value change it the list is been created from the start. The problem is that if im using a big file in my program the list is containing sometimes 16500 indexs and its taking time to loop over the list so i guess when im changing the numeric value its taking time to loop over the list. If im using smaller video file for example the list containing 4000 indexs so there is no problems. I tried to use Timer2 maybe i could wait 0.5 seconds between each time the numeric value is changed but still dosent work good.
When im changing the numeric value while the program is running on a big video file its taking the values to be changed like 1-2 seconds ! thats a lot of time.
Any way to solve it ? Maybe somehow to read the list loop over the list faster even if the list is big ?
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
Options_DB.Set_numericUpDownValue(numericUpDown1.Value);
if (isNumericChanged == true)
{
isNumericChanged = false;
myTrackPanelss1.trackBar1.Scroll -= new EventHandler(trackBar1_Scroll);
DoThresholdCheck();
counter = 0;
}
}
private void timer2_Tick(object sender, EventArgs e)
{
counter++;
if (counter > 1)
{
isNumericChanged = true;
//timer2.Stop();
}
}
This is the DoThresholdChecks() function code:
private void DoThresholdCheck()
{
List<string> fts;
//const string D6 = "000{0}.bmp";
if (Directory.Exists(subDirectoryName))
{
if (!File.Exists(subDirectoryName + "\\" + averagesListTextFile + ".txt"))
{
return;
}
else
{
bool trackbarTrueFalse = false ;
fts = new List<string>();
int counter = 0;
double thershold = (double)numericUpDown1.Value;
double max_min_threshold = (thershold / 100) * (max - min) + min;
//label13.Text = max_min_threshold.ToString();
_fi = new DirectoryInfo(subDirectoryName).GetFiles("*.bmp");
for (int i = 0; i < myNumbers.Count; i++)
{
if (myNumbers[i] >= max_min_threshold)
{
//f.Add(i);
string t = i.ToString("D6") + ".bmp";
if (File.Exists(subDirectoryName + "\\" + t))
{
counter++;
button1.Enabled = false;
myTrackPanelss1.trackBar1.Enabled = true;
trackbarTrueFalse = true;
label9.Visible = true;
// myTrackPanelss1.trackBar1.Scroll += new EventHandler(trackBar1_Scroll);
//myTrackPanelss1.trackBar1.Minimum = 0;
// myTrackPanelss1.trackBar1.Maximum = f.Count;
// myTrackPanelss1.trackBar1.Value = f.Count;
// myFiles = new Bitmap(myTrackPanelss1.trackBar1.Value);
}
else
{
label9.Visible = false;
trackbarTrueFalse = false;
button1.Enabled = true;
myTrackPanelss1.trackBar1.Enabled = false;
myTrackPanelss1.trackBar1.Value = 0;
pictureBox1.Image = Properties.Resources.Weather_Michmoret;
label5.Visible = true;
secondPass = true;
break;
}
//fts.Add(string.Format(D6, myNumbers[i]));
}
}
//myTrackPanelss1.trackBar1.Maximum = _fi.Length - 1;
if (myTrackPanelss1.trackBar1.Maximum > 0)
{
if (trackbarTrueFalse == false)
{
myTrackPanelss1.trackBar1.Value = 0;
}
else
{
myTrackPanelss1.trackBar1.Maximum = counter;
myTrackPanelss1.trackBar1.Value = 0;
SetPicture(0);
myTrackPanelss1.trackBar1.Scroll += new EventHandler(trackBar1_Scroll);
}
//checkBox2.Enabled = true;
}
if (_fi.Length >= 0)
{
label15.Text = _fi.Length.ToString();
label15.Visible = true;
}
}
}
else
{
button1.Enabled = true;
}
}
try to cache results from DoThresholdCheck method
You can't magically get around the time the processing takes, if the processing is really necessary. You've got a couple of avenues to explore:
1) Minimise the processing being done - is all of it necessary? Can you cache any of it and only recompute a small amount each time the value changes?
2) Do the processing less often - do you have to recompute every single time?
3) Do the processing on another thread - then at least your UI remains responsive, and you can deliver the results to the UI thread when the background task is complete. However, this is going to be a relatively complicated variant of this pattern as you're going to need to be able to abort and restart if the value changes again while you're still processing the previous one.

Categories

Resources