This code doesn't call function 200 times in 1 second, first time I get 167 calls, second time 201 but I don't get 200.
public Thread thread;
public Timer timer;
int i = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
timer = new Timer(Mess);
timer.Change(10000, 10000);
thread = new Thread(Calc);
thread.Start();
}
private void Mess(object state)
{
MessageBox.Show("Call in on second : " + (i / 10).ToString());
i = 0;
}
private void Calc(object obj)
{
while (true)
{
i++;
Thread.Sleep(5);
}
}
Its because of your scheduler wich manage the different threads in your processor. This process is not running all the time in your processor so strange behaviors can occur.
Programs using threads are rarely deterministic (it's why you get 167 for the first time ans 201 in the second time)
Because Windows is not a real-time operating system, it is difficult to achieve this kind of resolution.
The closest you are likely to get is by using the Windows API function CreateTimerQueueTimer(). This is a high-resolution timer, but it still might not be high enough resolution for your purposes.
You may still like to try it though. It's awkward to call from C# because it uses a callback function which Windows expects to be a native method. It's possible though, and here's an article on how to call it from C#.
Related
I am having a problem with my multi-threaded app on windows form C# application. This application works fine on multicore machine, but then when it runs in a single core machine all the threads hang. I'm using backgroundWorker, code follow as this:
class custonTime // delay class
{
public void sleep_sec(int sleep)
{
int time_now = Environment.TickCount;
int time_sleep = sleep;
while ((Environment.TickCount - time_now) < time_sleep) ;
}
}
When I press a button on UI the flags action and doAlways are set to true and the following backgroundworkers are started. The backgorundworker1 await and fire the task on right time the other one does the task:
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
while(action)
{
if(doItAlways)
{
//do important tasks
}
if(task1)
{
//do things
task1 = false;
}
if(task2)
{
//do things
task1 = false;
}
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
task1=true;
manegerTimewr2.sleep_sec(12000);//call delay class to wait 12 secs
task2=true;
manegerTimewr2.sleep_sec(12000);//call delay class to wait 12 secs
}
My delay class lock not just my backgorundworker1 but the backgroundworker2 as well, make impossible to do the tasks fired by flag doItAlways, the application is only released when the while loop finish.
And it just happens on single core machine only.
Is there another method? A direct and easy method to hang a thread until elapse some time without block the other ones?
Note Thread.Sleep won't work because the time elapsed varies too much on different machines.
The problem is, that BackgroundWorker use a thread pool internally which contains usually the same number of threads as you have CPUs/cores on the machine. Therefore on a single-CPU machine you'll have only one thread processing BackgroundWorkers, I guess they are scheduled sequentially so the first one runs both sleep_sec calls, and only after that, the second one starts.
On a multi-core machine on the other hand, you have more threads in the thread pool, therefore it works as you expect it.
You could use either a "normal" Thread (together with Thread.Sleep, dont use a while loop) for the "waiting", since this doesn't require any UI interaction. You could also just use a Timer object, which is meant for exactly this purpose (firing an event after a specified amount of time).
Implement waiting for a specified amount of time with this method: Thread.Sleep.
Instead of using a BackgroundWorker, instead launch a new Thread, and set the ThreadPriority for that thread manually. Then you'll be able to use Thread.Sleep and it should work more precisely since the thread is higher priority. Here's about what you should end up with:
void Run()
{
// some initialization stuff
new Thread(DoWork1) { Priority = ThreadPriority.AboveNormal }.Start();
new Thread(DoWork2) { Priority = ThreadPriority.Highest }.Start();
}
private void DoWork2()
{
while (action)
{
if (doItAlways)
{
//do important tasks
}
if (task1)
{
//do things
task1 = false;
}
if (task2)
{
//do things
task1 = false;
}
Thread.Sleep(1);
}
}
private void DoWork1()
{
task1 = true;
Thread.Sleep(12000);//call delay class to wait 12 secs
task2 = true;
Thread.Sleep(12000);//call delay class to wait 12 secs
}
I'm currently using a stopwatch as a global timer. I have main thread running, another thread, and an event method.
The main thread launches the other thread and the event method is triggered by events. Both methods will call the stopwatch and get its time. The thing is, the times are not consistent:
from main thread:
START REC AT 9282
STOp REC AT 19290
from another thread:
audio 1
audio 304
audio 354
audio 404
audio 444
audio 494
audio 544
audio 594
from event method:
video 4
video 5
video 29
video 61
video 97
video 129
video 161
I don't get why if i start my rec at 9282, the other two functions that call the stopwatch will have timers that start at zero? Is this a thread related issue? How can i fix this? Thanks
UPDATE:*********
when i save my frames i changed to:
long a = relogio.EllapseMilliseconds
i print out this value and its ok, as expected. but when i print the value stored in the lists, they come as starting from the beggining. strange huh?
SORRY FOR ALL THE TROUBLE, I PRINTED IT WITHOUT THE STARTING TIME,THATS WHY THEY ALL SEEMED TO START FROM ZERO! MANY THANKS AND SORRY!
main thread
private void Start_Recording_Click(object sender, RoutedEventArgs e)
{
rec_starting_time = relogio.ElapsedMilliseconds;
Console.WriteLine("START REC AT " + rec_starting_time);
write_stream.enableRecording();
Thread a = new Thread(scheduleAudioVideoFramePicks);
a.Start();
scheduleAudioVideoFramePicks - this thread just counts the time, so i know when to stop
//while....
if (rec_starting_time + time_Actual > rec_starting_time+recording_time * 1000)//1000 - 1s = 1000ms
{
totalRecordingTimeElapsed = true;
write_stream.disableRecording();
Console.WriteLine("STOp REC AT " + relogio.ElapsedMilliseconds);
}
//end while
lock (list_audio)
{
int b = 0;
//print time of frames gathered
foreach(AudioFrame item in list_audio){
Console.WriteLine("audio " + (item.getTime() - rec_starting_time));
}
lock (list_video)
{
}
foreach (VideoFrame item in list_video)
{
Console.WriteLine("video " + (item.getTime() - rec_starting_time));
}
}
the another thread, where i get the time
if (write_stream.isRecording())
{
list_audio.Enqueue(new AudioFrame(relogio.ElapsedMilliseconds, audioBuffer));
}
event method
if (write_stream.isRecording())
{
list_video.Add(new VideoFrame(relogio.ElapsedMilliseconds, this.colorPixels));
}~
i dont know if this is relevant, but i start my stopwatch like this
public MainWindow()
{
InitializeComponent();
//some code
this.relogio = new Stopwatch();
relogio.Start();
}
Stopwatch is not threadsafe, particularly for 32-bit programs.
It uses the Windows API call QueryPerformanceCounter() to update a private long field. On 32-bit systems you could get a "torn read" when one thread reads the long value while another thread is updating it.
To fix that, you'd have to put a lock around access to the Stopwatch.
Also note that one some older systems there were bugs where inconsistent values could be returned from different threads calling QueryPerformanceCounter(). From the documentation:
On a multiprocessor computer, it should not matter which processor is called. However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL). To specify processor affinity for a thread, use the SetThreadAffinityMask function.
I have never encountered this bug myself, and I don't think it's very common.
What results do you get with the following test program? The times should be mostly increasing in value, but you are liable to get one or two out of order just because their threads get rescheduled just after they've read a value and before they add it to the queue.
namespace Demo
{
class Program
{
Stopwatch sw = Stopwatch.StartNew();
object locker = new object();
ConcurrentQueue<long> queue = new ConcurrentQueue<long>();
Barrier barrier = new Barrier(9);
void run()
{
Console.WriteLine("Starting");
for (int i = 0; i < 8; ++i)
Task.Run(()=>test());
barrier.SignalAndWait(); // Make sure all threads start "simultaneously"
Thread.Sleep(2000); // Plenty of time for all the threads to finish.
Console.WriteLine("Stopped");
foreach (var elapsed in queue)
Console.WriteLine(elapsed);
Console.ReadLine();
}
void test()
{
barrier.SignalAndWait(); // Make sure all threads start "simultaneously".
for (int i = 0; i < 10; ++i)
queue.Enqueue(elapsed());
}
long elapsed()
{
lock (locker)
{
return sw.ElapsedTicks;
}
}
static void Main()
{
new Program().run();
}
}
}
Having said all that, the most obvious answer is that in fact you aren't sharing a single Stopwatch between the threads, but instead you have accidentally started a new one for each thread...
Intro:
I am developing software that uses motion trackers to analyse human motor systems. Currently I am implementing hardware from xsens and using their SDK to receive data from their wireless sensors.
The SDK offers a COM interface with a "getData" method which you call to receive the currently available xyz axis data (simplified). If you do not call getData, you skip that "beat" so you will be missing data, there is no caching in their hardware/SDK.
Problem:
My problem is that I need to get data at a rate of at least 75Hz, preferably a bit more, but 75 would be acceptable, but I am currently quickly dropping to just 20 signals per second...
If I remove the processing bit (see the sample below) I get perfect sample rates, so I think either the dequeue is causing the enqueue to pause. Or the "heavy" CPU load is causing all threads to wait. I have no idea how to figure out what is actually causing it, the profiler (EQATEC) just shows my "GetData" method is taking longer after a while.
Question:
What is the best technique to use to accomplish this? Why would my "reading" thread be interrupted/blocked? There must be more cases where people need to read from something without being interrupted, but I have been Googleing for 2 weeks now and apparently I can't find the correct words.
Please advise.
Thanks
Simplified code sample, version 4, using a MultiMedia timer (http://www.codeproject.com/Articles/5501/The-Multimedia-Timer-for-the-NET-Framework) and a BackgroundWorker
public class Sample
{
private MultiMediaTimer _backgroundGetData;
private bool _backgroundGettingData;
private BackgroundWorker _backgroundProcessData;
private ConcurrentQueue<double> _acceleration = new ConcurrentQueue<double>();
private void StartProcess()
{
if (_backgroundGetData == null)
{
_backgroundGetData = new MultiMediaTimer {Period = 10, Resolution = 1, Mode = TimerMode.Periodic, SynchronizingObject = this};
_backgroundGetData.Tick += BackgroundGetDataOnTick;
}
_backgroundProcessData = new BackgroundWorker {WorkerReportsProgress = false, WorkerSupportsCancellation = true};
_backgroundProcessData.DoWork += BackgroundProcessDataOnDoWork;
_backgroundGetData.Start();
}
private void BackgroundProcessDataOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
double value;
if (!_acceleration.TryDequeue(out value)) value = 0;
//Do a lot of work with the values collected so far,
//this will take some time and I suspect it's the cause of the delays?
}
private void BackgroundGetDataOnTick(object sender, EventArgs eventArgs)
{
if (_backgroundGettingData) return;
_backgroundGettingData = true;
//123 represents a value I am reading from the sensors using the SDK
double value = 123;
if (value == -1)
{
Thread.Sleep(5);
continue;
}
_acceleration.Enqueue(value);
if (_acceleration.Count < 5) continue;
if (!_backgroundProcessData.IsBusy)
{
_backgroundProcessData.RunWorkerAsync();
}
_backgroundGettingData = false;
}
}
I am seeing the problem here
_backgroundProcessDataThread.Start();
while (!_backgroundProcessDataThread.IsAlive){}
_backgroundGetDataThread.Start();
while (!_backgroundGetDataThread.IsAlive) {}
Well, you can see here that you are having infinite loop here and the second thread starts only after first has finished its work. i.e. first thread is done. This is in no way an ideal model.
Sorry, I recognized the issue later.
The problem is, _backgroundGetDataThread will start only after _backgroundProcessDataThread has done its work.
I have created a new Windows Forms Application with C# and .NET 4.0, and I have a function that must be called automatically every 60th of a second. My problem, is that I do not know where to call this function. .NET forms don't appear to have a built-in on-update event.
How would I go about getting this function called every 60th of a second?
Sorry if it is a beginner question.
You could set up a Timer to invoke a callback every 16 ms (which is 1/60 sec).
Important point as mentioned by #spender: If you are requiring very precise timing on this, eg exactly every 1/60 sec precision, you will not be satisfied with this solution. Windows does not natively do high-resolution timing in that vein very well. Props to #spender for the mention.
Here's a sample class with a rough outline of how it might look in a plain vanilla class, so you'd need to adapt it to your form:
You might also want to call this on a background thread, but if you're new to WinForms, we'll start in small chunks. Let's try the timer first, then go from there.
class Demo{
System.Timers.Timer myTimer;
void InitializeTimer(){
myTimer = new Timer(16); // elaps every 1/60 sec , appx 16 ms.
myTimer.ElapsedEventHandler+=new ElapsedEventHandler(myTimerEventHandler); //define a handler
myTimer.Enabled=true; //enable the timer.
}
void myTimerEventHandler(object sender, ElapsedEventArgs e){
// do your thing here
}
}
EDIT: Extra demo code for background thread creation and Invoked-based GUI update
As noted in my comment below, this is not as polished as I would like it, but I think it illustrates the salient points. It defines a BackgroundWorker thread to move the thread invocations to the background; the thread callback checks for the need to call Invoke, and calls right back to itself across a delegate invocation to allow for the custom form update in the "else" block of the "if (InvokeRequired)" statement. In a nutshell, a background thread starts, and starts a timer; when the timer elapses, it calls the updater on the background thread, which checks to see if Invoke must be called, and if it is, performs the thread context switch back to the GUI thread through the recall to the method, which then performs the GUI update. Put your custom update code in that "else" block. I hope this helps!!!
public partial class Form1 : Form
{
delegate void FormUpdateDelegate(object sender, ElapsedEventArgs e);
public BackgroundWorker backgroundThread;
System.Timers.Timer foo;
Random colorgen = new Random();
public Form1()
{
InitializeComponent();
backgroundThread = new BackgroundWorker();
backgroundThread.DoWork+=new DoWorkEventHandler(backgroundThread_DoWork);
backgroundThread.RunWorkerAsync();
}
public void formUpdater(object sender, ElapsedEventArgs e)
{
if (InvokeRequired)
{
FormUpdateDelegate d = new FormUpdateDelegate(formUpdater);
Invoke(d, new object[] { sender, e });
}
else
{
// Do your form update here
this.label1.ForeColor = Color.FromArgb(colorgen.Next());
}
}
public void backgroundThread_DoWork(object sender, DoWorkEventArgs e)
{
foo = new System.Timers.Timer(16);
foo.Elapsed += new ElapsedEventHandler(formUpdater);
foo.Start();
}
}
I just setup this in a console application, and it runs fine every second:
var timer = new System.Timers.Timer(1000);
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(delegate(object sender, ElapsedEventArgs eventArgs)
{
Console.WriteLine("Elapsed");
});
It is a bad practice to hope on system timers when you need precision at least 20 times per second.
I would recommend to use cycles like
Timespan timePerFrame = Timespan.FromMilliseconds(16);
while (_isRunning)
{
Stopwatch timer = Stopwatch.StartNew()
// Action.
while (timer.ElapsedMilliseconds < timePerFrame) { /* Nothing? */ }
}
That will give you the full precision, if your system supports high-precision stopwatch. (.IsHighResolution field).
I have a requirement for a timer that has the following behaviour:
Millisecond accuracy
I want the tick event handler to only be called once the current tick handler has completed (much like the winforms timer)
I want exceptions on the main UI thread not to be swallowed up by the thread timer so this requires Invoke/Send instead of BeginInvoke/Post
I've played around with CreateTimerQueueTimer and had some success but at the same time had problems with code reentrance and/or locks when deleting the timer.
I decided to create my own timer so that I could get a better idea of what is going on under the hood so that I can fix the locking and reentrance problems. My code seems to work fine leading me to believe that I may as well use it. Does it look sound?
I've put in a check if the timer is deleted to make sure that the deletion is complete before the timer can be created again. Does that look ok?
Note: I should say that I call timeBeginPeriod(1) and timeEndPeriod(1) inorder to achieve the millisecond accuracy.
(The following code is converted from vb.net to c#, so apologies for any missed mess-ups}
ETA: I've found a problem with it. If the timer is running at an interval of 1 millisecond, and I call, say, Change(300), it locks up # while (this.DeleteRequest). This
must be because the TimerLoop is in the this.CallbackDelegate.Invoke(null) call.
public class MyTimer : IDisposable
{
private System.Threading.TimerCallback CallbackDelegate;
private bool DeleteRequest;
private System.Threading.Thread MainThread;
public MyTimer(System.Threading.TimerCallback callBack)
{
this.CallbackDelegate = callBack;
}
public void Create(int interval)
{
while (this.DeleteRequest) {
System.Threading.Thread.Sleep(0);
}
if (this.MainThread != null) {
throw new Exception("");
}
this.MainThread = new System.Threading.Thread(TimerLoop);
// Make sure the thread is automatically killed when the app is closed.
this.MainThread.IsBackground = true;
this.MainThread.Start(interval);
}
public void Change(int interval)
{
// A lock required here?
if (!this.IsRunning()) {
throw new Exception("");
}
this.Delete();
this.Create(interval);
}
public void Delete()
{
this.DeleteRequest = true;
}
public bool IsRunning()
{
return (this.MainThread != null) && this.MainThread.IsAlive;
}
private void TimerLoop(object args)
{
int interval = (int)args;
Stopwatch sw = new Stopwatch();
sw.Start();
do {
if (this.DeleteRequest) {
this.MainThread = null;
this.DeleteRequest = false;
return;
}
long t1 = sw.ElapsedMilliseconds;
// I want to wait until the operation completes, so I use Invoke.
this.CallbackDelegate.Invoke(null);
if (this.DeleteRequest) {
this.MainThread = null;
this.DeleteRequest = false;
return;
}
long t2 = sw.ElapsedMilliseconds;
int temp = Convert.ToInt32(Math.Max(interval - (t2 - t1), 0));
sw.Reset();
if (temp > 0) {
System.Threading.Thread.Sleep(temp);
}
sw.Start();
} while (true);
}
// The dispose method calls this.Delete()
}
I would recommend using p/Invoke and using the timers from Win32's Timer Queues:
http://msdn.microsoft.com/en-us/library/ms686796(v=vs.85).aspx
One should be mindful that the managed CLR environment has a lot of non-determinism built into it, garbage collection, for instance. Just because your timer is has a period of 1 millisecond doesn't mean that that is necessarily what happens.
Also, the documentation doesn't mention it, but the callback invoked by the timer must be pinned in memory and not garbage collectable, via a GCHandle or other construct. When a timer (or timers, if you kill off a timer queue), the callback will be executed one last time. Not sure whether that happens by the internal wait expiring, or by signalling the internal event handle.
Execution of DeleteTimerQueueTimer() and DeleteTimerQueueEx() can be made synchronous, so they won't return until all timers have signalled and invoked their last callback, but doing that would be suboptimal.
If you don't pin the callbacks and prevent them from being garbage-collected, things will go swimmingly...most of the time. You'll encounter random exceptions.
Also, the callback should be smart enough to bail out if the timer is being deleted, lest it make reference to something that's already GC'd.
μTimer would be a better example!
You can find it here # https://stackoverflow.com/questions/15725711/obtaining-microsecond-precision-using-net-without-platform-invoke?noredirect=1#comment22341931_15725711
It provides accurate wait times down to 1µs and possibly lower depending on your NIC!
Let me know if you need anything else!