I have a block of code that will be called relatively often. Prior to it being called I need a 2000ms delay to take place.
The first thing that has come to mind is creating/disposing of a timer every time the method is called.
To accomplish this I'm using a Timer (see code). My question is...any dangers/problems calling Dispose inside of the anonymous method below? Recommendations of a better approach?
Are there any downsides to doing the following? Bad idea?
delayTimer = new Timer() { Interval = 2000 };
{
delayTimer.Tick += (sender2, e2) =>
{
((Timer)sender2).Stop();
MessageBox.Show("Do something after 2000ms");
delayTimer.Dispose();
};
}
One thing you can do differently is move the Dispose for the timer to the front of the anonymous method. This way, even if you throw an exception later in the method, you've still Disposed the timer. I've used this kind of pattern before and it's a reasonably clean way to get a delayed callback.
If you're using C#5, there is a very nice Task.Delay method you can await to get a timer callback within an async method. This is often used to implement timeouts in combination with a call to WaitAny like this:
public static async Task WithTimeout(this Task task, int timeout, string timeoutMessage = null, params object[] args)
{
var timeoutTask = Task.Delay(timeout);
if (await Task.WhenAny(task, timeoutTask) == timeoutTask)
throw new TimeoutException(timeoutMessage == null ? "Operation timed out" : string.Format(timeoutMessage, args));
await task;
}
Very strange task, but ok.
If you really need to do this, you really want to use a timer, and that block of code will really be called very often, than you should consider to use a cache of timers.
Each time the block of code is called, you should check the cache whether it contains a free timer. If yes, than just use the first available, otherwise, create a new one and put it into the cache. Also, you will need an another timer which will work all the time and will regularly check the cache for an unused timers. If some timer or timers are unused for lets say 10 seconds, than dispose it and remove from cache. Such approach will significantly reduce the number of created instances of timers.
You need a cache only in case if you create timers really very often (hundreds times per second), because multiple creation and disposing such heavy object as Timer (it uses some system resources) can lead to a performance issue. But from your detailed description it is obvious that you are not going to create timers so often, so you can keep your solution. But instead of using timer, you can use RX's Interval observable collection, and all your code will be shortened to 1 string:
Observable.Interval(TimeSpan.FromSeconds(2)).Take(1).Subscribe(_ => MessageBox.Show("Do something after 2000ms"));
I didn't have any serious performance issues creating a thousand timers with your code.
Disposing of a Timer (or any IDisposable) within an anonymous method is no problem at all.
However, your code isn't written in the best way possible. Try this implementation instead:
var delayTimer = new Timer()
{
Interval = 2000,
Enabled = true,
};
EventHandler tick = null;
tick = (_s, _e) =>
{
delayTimer.Tick -= tick;
delayTimer.Stop();
delayTimer.Dispose();
MessageBox.Show("Do something after 2000ms");
};
delayTimer.Tick += tick;
It's always a good idea to detach the event before trying to dispose of the timer. In fact there may be many times that failing to detach will not allow the GC to clean up properly and you could have a memory leak.
Nevertheless I do like the Rx answer to this question as the cleanest way to go. Although using Rx doesn't marshall the callback on the UI thread unless you do this:
Observable
.Timer(TimeSpan.FromSeconds(2.0))
.ObserveOn(this) // assuming `this` is your form
.Subscribe(_ => MessageBox.Show("Do something after 2000ms"));
Much simpler.
Related
I want to run a function on an interval, inside of a Task. Something like,
Task t = Task.Factory.StartNew(() => {
while (notCanceled()) {
doSomething();
Thread.Sleep(interval);
}
});
Is it a bad idea to use Thread.Sleep() here? The task is long running, and the sleep time may also be very long (minutes, maybe even hours).
One alternative is to use either System.Timers.Timer or System.Threading.Timer. However both of these would cause an additional thread to spawn (the Elapsed events occur on a new threadpool thread). So for every repeating task, there would be 2 threads instead of 1. The Task is already asynchronous so I'd prefer not to complicate things in this way.
Yet another way that behaves similarly is to use ManualResetEvent,
ManualResetEvent m = new ManualResetEvent(false);
void sleep(int milliseconds)
{
m.WaitOne(milliseconds);
}
Since m.Set() would never be called, this would always wait for the right amount of time, and also be single threaded. Does this have any significant advantage over Thread.Sleep()?
Wondering what the best practice would be here.
Thoughts?
If you're using C# 5.0 you can use:
while(notCanceled())
{
doSomething();
await Task.Delay(interval);
}
If you're using an earlier version your best bet is probably to use a Timer.
Both of the code samples you showed, involving either Thread.Sleep or a ManualResetEvent are blocking the current thread for that duration, which means your code is tying up a thread which can't do anything else until your task is canceled. You don't want to do that. If you use a timer, or the await code mentioned above, you will end up not blocking any thread at all while waiting, and then use up a thread pool's time only when you have productive work to be doing.
Yes, it is a very bad idea to use sleep in a loop like that.
You have a faulty understanding of timers. Creating a timer does not create a new thread. The timer sets an operating system trigger that, when the time elapses, spawns a threadpool thread. So if you write:
System.Threading.Timer myTimer =
new Timer(DoStuff, null,
TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
The only time there will be another thread is when the handler method (DoStuff) is executing.
There'd be no reason to have the task if everything it does is handled by your DoStuff method. If you want to cancel it, just dispose the timer.
I strongly recommend, by the way, that you not use System.Timers.Timer. In short, it squashes exceptions, which hides bugs. See Swallowing exceptions is hiding bugs.
I need to do some pretty fast recalculation ~every second.
What is the best way to do that? Is using dedicated thread and Thread.Sleep is ok?
Task.Factory.StartNew(() =>
{
while (true)
{
RecalculateState();
Thread.Sleep(1000);
}
}, TaskCreationOptions.LongRunning);
That would work - but another alternative would be to use a timer, e.g. System.Threading.Timer or System.Timers.Timer.
You should think about:
What do you want to happen if it takes more than a second to recalculatte state?
Is your RecalculateState method entirely safe to be called from arbitrary threads?
You can use System.Timers.Timer with 1 second interval.
It already runs in a new thread .
Pay attention on fact, that if RecalculateState runs longer than expected interval (for 1000 of reasons) you have to deal with calls overlapping, so you have to manage that case in some way.
One of possible solutions, is to run a new code only after execution of the method finished, and measure difference between execution time and interval. But this is not so easy task to do. Fortunatelly someone already thought about that problem.
Can have a look on Reactive Extensions that in latest build payed special attention on time dependent execution.
Can't you use a timer and make a ontimed event?
Something like this ?
Observable.Timer(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(1)).Timestamp()
.Subscribe(MyOnTimedEventMethod);
I would suggest to use a timer for this.
member:
private readonly Timer _timer;
instantiate the timer in the constructor for instance:
_timer= new Timer(OnTimerEllapsed, null, 0, 1000);
callback:
private void OnTimerEllapsed(object sender)
{
RecalculateState();
}
I have a rather large class which contains plenty of fields (10+), a huge array (100kb) and some unmanaged resources. Let me explain by example
class ResourceIntensiveClass
{
private object unmaganedResource; //let it be the expensive resource
private byte[] buffer = new byte[1024 * 100]; //let it be the huge managed memory
private Action<ResourceIntensiveClass> OnComplete;
private void DoWork(object state)
{
//do long running task
OnComplete(this); //notify callee that task completed so it can reuse same object for another task
}
public void Start(object dataRequiredForCurrentTask)
{
ThreadPool.QueueUserWorkItem(DoWork); //initiate long running work
}
}
The problem is that the start method never returns after the 10000th iteration causing a stack overflow. I could execute the OnComplete delegate in another thread giving a chance for the Start method to return, but it requires using extra cpu time and resources as you know. So what is the best option for me?
Is there a good reason for doing your calculations recursively? This seems like a simple loop would do the trick, thus obviating the need for incredibly deep stacks. This design seems especially problematic as you are relying on main() to setup your recursion.
recursive methods can get out of hand quite fast. Have you looked into using Parallel Linq?
you could do something like
(your Array).AsParallel().ForAll(item => item.CallMethod());
you could also look into the Task Parallel Library (TPL)
with tasks, you can define an action and a continue with task.
The Reactive Framework (RX) on the other hand could handle these on complete events in an async manner.
Where are you changing the value of taskData so that its length can ever equal currentTaskIndex? Since the tasks you are assigning to the data are never changing, they are being carried out forever...
I would guess that the problem arises from using the pre-increment operator here:
if(c.CurrentCount < 10000)
c.Start(++c.CurrentCount);
I am not sure of the semantics of pre-increment in C#, perhaps the value passed to a method call is not what you expect.
But since your Start(int) method assigns the value of the input to this.CurrentCount as it's first step anyway, you should be safe replacing this with:
if(c.CurrentCount < 10000)
c.Start(c.CurrentCount + 1);
There is no point in assigning to c.CurrentCount twice.
If using the threadpool, I assume you are protecting the counters (c.CurrentCount), otherwise concurrent increments will cause more activity, not just 10000 executions.
There's a neat tool called a ManualResetEvent that could simplify life for you.
Place a ManualResetEvent in your class and add a public OnComplete event.
When you declare your class, you can wire up the OnComplete event to some spot in your code or not wire it up and ignore it.
This would help your custom class to have more correct form.
When your long process is complete (I'm guessing this is in a thread), simply call the Set method of the ManualResetEvent.
As for running your long method, it should be in a thread that uses the ManualResetEvent in a way similar to below:
private void DoWork(object state)
{
ManualResetEvent mre = new ManualResetEvent(false);
Thread thread1 = new Thread(
() => {
//do long running task
mre.Set();
);
thread1.IsBackground = true;
thread1.Name = "Screen Capture";
thread1.Start();
mre.WaitOne();
OnComplete(this); //notify callee that task completed so it can reuse same object for another task
}
I have a Windows Application. We have implemented AutoSave functionality as background process.
Sample code is as below:
While(1)
{
Thread.Sleep(60000) // 1 minute sleep
DoAutoSaveAllControls();
}
I think this is bad functionality. Correct me if I am wrong. But, I want to improve performance and do this task after certain time interval, without doing Sleep.
Also, is it good to do this in background process?
A much better approach would be to use a timer. You can find out about the various different timers in the .NET framework from this excellent article:
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
You are using WinForms, so a System.Windows.Forms.Timer will be just fine for you.
For example:
System.Windows.Forms.Timer tmrWindowsFormsTimer = new System.Windows.Forms.Timer();
tmrWindowsFormsTimer.Interval = TimeSpan.FromMinutes(1);
tmrWindowsFormsTimer.Tick += new EventHandler(tmrWindowsFormsTimer_Tick);
tmrWindowsFormsTimer.Start();
private void tmrWindowsFormsTimer_Tick(object sender, System.EventArgs e) {
tmrWindowsFormsTimer.Stop();
DoAutoSaveAllControls();
}
This stops the timer after the first tick, effectively a fire-once timer.
You can use Reactive Extenssions for this as well.It looks more natural and you can combine observables.
var observable = Observable.Timer(
TimeSpan.FromMinutes(1),
TimeSpan.FromMinutes(1)).Timestamp();
using (observable.Subscribe()))
{
DoAutoSave();
}
Thread.Sleep does not affect performance at all. In order to me is perfectly ok, but since your application is probably modifying the document in the UI thread you probably need to sincronize the save in order to avoid concurrent modifications. Just for this reason maybe it would be better to use a Timer instead of BackGroundWorker.
You're right, it's not really a good use of a thread. Take a look at the Timer class.
You can use System.Timers.Timer to start a process after certain interval, check the sample snippet
aTimer = new System.Timers.Timer(10000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(YourHandlerMethod);
// Set the Interval to 2 seconds (2000 milliseconds).
aTimer.Interval = 2000;
aTimer.Enabled = true;
I think you need to trigger save functionality from the calling code (that knows if any changes had already happaned). So that saving thread could know for sure that calling thread has made some changes to save.
This is not an answer for this question, just maybe recommendation. So if you are calling Save from inside of timer, you should verify first if any change happened. To do that you'll need some additional variable, that would be common for working thread and saving thread. If working thread did change something, it triggers that var to true. When saving, if var is true - then saving is needed. After saving - change common var to false.
I want to wait for 15 seconds, then the control should resume from the next statement.
I don't have anything else to do while waiting (Just waiting).
I know that there is Thread.Sleep(15000). What I don't know is the best method to wait? What are the limitations of this?
The code would be like this:
Method()
{
statement 1;
statement 2;
//WaitFor 15 secs here;
statement 3;
}
The disadvantage of Thread.Sleep is if this is called in your GUI thread (the thread that processes GUI events, for example, a button click handler method, or a method called from a button click handler, etc.) then you application will appear to freeze and be nonresponsive for those 15 seconds.
It would be perfectly fine if you had explicetly created a seperate thread and called Thread.Sleep in it, assuming you don't mind that thread not doing anything for 15 seconds.
The alternative would be to create a Timer and start it after stmt 2, and place stmt 3 in the Tick event handler for the timer, and also stop the timer in that handler.
This may not be a direct answer to your question. I would say check whether your process flow is better than checking whether the code is better ;-)
Are you waiting for 15 seconds just to make sure stmt2; is complete? If so then adding an handler, as soon as stmnt 2 is executed, would be a better solution (?)
You can also use a timer to wait. Thread.sleep is a bad design. We have a similar question which talks about the comparison using Thread.sleep and Timer.
Try something like the following:
void Method()
{
console.log('statement 1');
console.log('statement 2');
var timer = new System.Threading.Timer(
o => // timer callback
{
console.log('statement 2');
},
15000, // Delay
0 // Repeat-interval; 0 for no repeat
);
}
Syntax is C# 3.0, uses a lambda expression to effectively create a closure around statement #3. With this, you could use any local variables of Method. A thing to note, however, is that with this method, or any other timer-based method...the function will return immediately after creating the timer. The function won't block until the Timer executes. To achieve that, the only thing I can think of is to actually use threads and make Method() block on a signal (i.e. WaitHandle, ResetEvent, etc.) until the timed call on the other thread completes.
Thread.sleep seems a sensible thing to do if there isn't anything else to do while waiting.
It puts the thread to sleep for that time so it doesn't use any CPU resources.
You could always use a timer and then execute code after the set duration. However, if you don't actually have to do anything and just want to wait at a particular point in code, then I think Thread.Sleep(150000); is sufficient.
[Edit: spelling]
If you always want to wait for a given time, then Sleep is useful. Obviously you shouldn't do this on a thread where timely responses are expected.
Keep in mind that your thread will sleep for the duration in all cases. If for some reason you want the thread to resume sooner, you're better off using signaling or callbacks. By using either of these instead of Sleep, you will minimize the needless wait time.
void Method()
{
Statement1();
Statement2();
// Start the timer for a single 15 second shot.
// Keep a reference to it (Mytimer) so that the timer doesn't get collected as garbage
Mytimer = new System.Threading.Timer((a) =>
{
// Invoke the 3rd statement on the GUI thread
BeginInvoke(new Action(()=>{ Statement3(); }));
},
null,
15000, // 15 seconds
System.Threading.Timeout.Infinite); // No repeat
}
I don't sure 100%, but if you really need your method to return after waiting 15 sec, try following:
Method()
{
stmt1();
stmt2();
int time = DateTime.Now.Millisecond;
while (15*1000 > DateTime.Now.Millisecond - time)
{
Thread.Sleep(10)
Application.DoEvents();
}
stmt3();
}