How to estimate method execution time? - c#

I have requirement to cancel method execution if it takes the more than two seconds to complete and restart it on another thread.
So, is there any way/call back mechanism/HACK, I can make method inform me that it crossed 2 seconds time limit?

check if network drive exists with timeout in c#
https://web.archive.org/web/20140222210133/http://kossovsky.net/index.php/2009/07/csharp-how-to-limit-method-execution-time
Async Pattern:
public static T SafeLimex<T>(Func<T> F, int Timeout, out bool Completed)
{
var iar = F.BeginInvoke(null, new object());
if (iar.AsyncWaitHandle.WaitOne(Timeout))
{
Completed = true;
return F.EndInvoke(iar);
}
F.EndInvoke(iar); //not calling EndInvoke will result in a memory leak
Completed = false;
return default(T);
}

You should create System.Threading.Timer on two seconds, and run your method in another thread and wait for callback from it, if method completes before timer runs you should dispose timer, otherwise you should abort thread in which you method are executing. This is pretty simple for example
using (new Timer(BreakFunction, true, TimeSpan.FromMinutes(2), Timeout.Infinite))
{
//TODO:here you should create another thread that will run your method
}
In BreakFunction you should abort thread that runs your methods

It would be good if you can find it. I've been looking for it too.
What I usually do is start the method in another Thread, and start a Timer with 2 seconds in this case. The first time it raises the event, just do:
if (a.IsAlive)
{
a.Abort();
}
Two important things:
The Thread declared should be visible by the method that handles the timer
When calling Abort(), it raises ThreadAbortException, so you should correctly handle it in the method.

Related

C# timer callback

if I set a timer like this:
var MyTimer = new Timer(RunTask, AutoEvent, 1000, 2000);
is it guaranteed that RunTask will always be run on the same thread?
all my tests seem to indicate that it is the case, but is it a guarantee or luck?
this is quite important since I need to store variables that persist call to call and I'm currently using the [ThreadStatic] attribute on them.
I know that if the call back is holding the thread longer than the timer delay, the timer will do another callback on another thread; so I narrow the question to the case where there are no parallel runs (I block teh timer during the callback).
The System.Threading.TimerCallback delegate allows you to pass a context object to the callback method. You can use this context object to pass the state that you need in the callback handler. This way it wont matter what thread you are called back on, as you won't need to use ThreadStatic.
The state argument that you pass to the Timer constructor will be passed to the callback method.
To answer your question, no there is no such thing as a "reserved" thread for the TimerCallback. The event is scheduled on a ThreadPool and there is no guarantee that the next tick will happen on the same thread, even tho it is possible.
A simple test illustrates this:
myTimer = new System.Threading.Timer(timer_Elapsed, null, 0, Timeout.Infinite);
static void timer_Elapsed(object state)
{
Thread.Sleep(100);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
myTimer.Change(100, Timeout.Infinite);
}
And the results:

Synchronizing Events

I noticed that sometimes my code becomes out of sync if an event fires too quickly. I was wondering if there was a better approach. Under a normal scenario the DeviceOpenedEvent fires after I tell the thread to WaitOne in the TestDevice method, but I have seen in some cases where the event gets fired before the thread has a chance to wait.
protected AutoResetEvent TestAutoResetEvent = new AutoResetEvent(false);
public EventEnum WaitForEvent = EventEnum.None;
bool TestDevice()
{
OpenDevice();
WaitForEvent = EventEnum.DeviceOpened;
TestAutoResetEvent.WaitOne();
WaitForEvent = EventEnum.NoWait;
//Continue with other tests
}
void DeviceOpenedEvent()
{
if (WaitForEvent == EventEnum.DeviceOpened)
TestAutoResetEvent.Set();
}
Under normal circumstances it looks like this:
Open Device
WaitOne()
DeviceOpenedEvent occurs
Set()
This is what I'm seeing my logs sometimes:
Open Device
DeviceOpenedEvent occurs
WaitOne() Essentially stuck here forever
Since OpenDevice is asynchronous (as you mentioned in a comment), it runs in a different thread than its caller. Sometimes it will finish before the next line in source executes:
OpenDevice(); // Async: may finish before the next line executes!
WaitForEvent = EventEnum.DeviceOpened;
When that happens DeviceOpenedEvent doesn't do what you want it to, because WaitForEvent is still EventEnum.None:
if (WaitForEvent == EventEnum.DeviceOpened)
TestAutoResetEvent.Set();
The solution is to change your code so that you signal completion inside a method that's guaranteed to run in the correct order. Here's a simple implementation that removes the enumeration and uses a single wait handle for each event you need to wait on:
protected AutoResetEvent deviceOpenedEvent = new AutoResetEvent(false);
protected AutoResetEvent deviceLockedEvent = new AutoResetEvent(false);
bool TestDevice() {
OpenDevice();
// Do some unrelated parallel stuff here ... then
deviceOpenedEvent.WaitOne();
LockDevice();
deviceLockedEvent.WaitOne();
}
void DeviceOpenedEvent() {
deviceOpenedEvent.Set();
}
It's even easier if you control OpenDevice: just call deviceOpened.Set() when it's done. You could even change OpenDevice to accept the auto reset event and construct it right inside TestDevice, which would reduce your exposure to multithreading bugs.
This should not be a problem. The documentation for AutoResetEvent states:
If a thread calls WaitOne while the
AutoResetEvent is in the signaled
state, the thread does not block.
The following code does not cause WaitOne to block, for instance:
AutoResetEvent waitHandle = new AutoResetEvent(false);
waitHandle.Set();
waitHandle.WaitOne();
Console.WriteLine("After WaitOne");

Windows Service with AutoResetEvent

I'm currently building a Windows Service which needs to process a queue of messages that are sat in a database table. This queue could vary in length and could take anything from 5 seconds to 55 seconds to execute against all rows in the database (I'm currently using a test data set of 500,000 records)
The Windows Service is configured to run on a 30 second timer so I have tried, unsuccessfully, to ensure that when the timer delegate runs that it is not able to run again until the previous request to the method has completed successfully
I have the following code in my Windows Service OnStart method:
AutoResetEvent autoEvent = new AutoResetEvent(false);
TimerCallback timerDelegate = new TimerCallback(MessageQueue.ProcessQueue);
Timer stateTimer = new Timer(timerDelegate, autoEvent, 1000, Settings.Default.TimerInterval); // TimerInterval is 30000
autoEvent.WaitOne();
And the following code in MessageQueue.ProcessMessage:
Trace.Write("Starting ProcessQueue");
SmtpClient smtp = new SmtpClient("winprev-01");
AutoResetEvent autoEvent = (AutoResetEvent)stateObject;
foreach (MessageQueue message in AllUnprocessed)
{
switch (message.MessageType)
{
case MessageType.PlainText:
case MessageType.HTML:
SendEmail(smtp, message);
break;
case MessageType.SMS:
SendSms(message);
break;
default:
break;
}
}
autoEvent.Set();
Trace.Write("Ending ProcessQueue");
I'm using DebugView to analyse the view the Trace statements as the Service runs and I can see multiple instances of "Starting ProcessQueue" which occur every 30 seconds which is what I am trying to avoid happening
In summary: I want to call ProcessQueue and ensure that it is not executed again unless it has completed its work (this enables me to prevent the same messages in the queue being processed multiple times
I'm sure I'm missing something pretty obvious here so any help would be much appreciated :)
Dave
Why don't you have your delegate disable the timer and then re-enable it (or continue working, if timer would expire immediately) once it's through working. Provided the latency between timer firing and your delegate waking up is < 30 seconds, this should be watertight.
while (true)
{
Trace.Write("Starting ProcessQueue")
stateTimer.Enabled = false;
DateTime start = DateTime.Now;
// do the work
// check if timer should be restarted, and for how long
TimeSpan workTime = DateTime.Now - start;
double seconds = workTime.TotalSeconds;
if (seconds > 30)
{
// do the work again
continue;
}
else
{
// Restart timer to pop at the appropriate time from now
stateTimer.Interval = 30 - seconds;
stateTimer.Enabled = true;
break;
}
}
Your ProcessMessage is never checking if the resetEvent is signaled - it's just running regardless.
I post here how to fix this. However, this is not the ideal method to do what you want to do. See the bottom of my answer for that.
You have your call to autoEvent.WaitOne() in the wrong place; it should be at the beginning of the ProcessMessage method.
AutoResetEvent autoEvent = (AutoResetEvent)stateObject;
autoEvent.WaitOne();
Trace.Write("Starting ProcessQueue");
SmtpClient smtp = new SmtpClient("winprev-01");
foreach (MessageQueue message in AllUnprocessed){
You should also use the overload that accepts a time out value (int or timespan), and returns a bool If the method returns true, that means it was signaled, so you can continue. If it times out (because another iteration is still running), you should just return and not try to run the code again.
If you do not use such an overload, what you are doing would be no different than wrapping the ProcessMessage method's code in a critical section (lock() on a global var, for instance) - additional threads would block, and then needlessly run.
AutoResetEvent autoEvent = (AutoResetEvent)stateObject;
//wait just one ms to see if it gets signaled; returns false if not
if(autoEvent.WaitOne(1)){
Trace.Write("Starting ProcessQueue");
SmtpClient smtp = new SmtpClient("winprev-01");
foreach (MessageQueue message in AllUnprocessed){
Note that actually, a *ResetEvent isn't ideal here. You really just want to check if an instance is already running, and abort if so. ResetEvents aren't really made for that... but I wanted to address the question of using the ResetEvent anyway.
What would probably work better is to simply shut down the timer when the callback is called, and then restart it up when you are done. That way, it's impossible for that code to be re-entered while it's still running.
You absolutely would need to wrap all the code in the callback method in a try / finally though, so that you always restart the timer after.
You can trivially solve this by using a System.Threading.Timer. You make it a one-shot timer by setting its period to zero. Restart the timer in the callback. Overlapped execution of the callback is now impossible.
Since you run this so frequently, a different approach is to use a thread instead. You'll need an AutoResetEvent to signal the thread to stop in the OnStop() method. Its WaitOne() method gives you a free timer when you use the overload that takes the millisecondsTimeout argument.
Btw: note that the autoEvent.WaitOne() call in OnStart() is troublesome. It may timeout the service controller if the first email takes a long time to send. Just omit it, you got the timer started == service started.
I think you are making this a lot harder than it needs to be. Why not just create a separate thread that spins around an infinite loop calling MessageQueue.ProcessQueue and then waiting a certain amount of time before calling it again. If it is all happening on a single thread there is no way for anything to happen in parallel.
public class YourService : ServiceBase
{
private ManualResetEvent m_Stop = new ManualResetEvent(false);
protected override void OnStart(string[] args)
{
new Thread(Run).Start();
}
protected override void OnStop()
{
m_Stop.Set();
}
private void Run()
{
while (!m_Stop.WaitOne(TimeSpan.FromSeconds(30))
{
MessageQueue.ProcessMessage();
}
}
}
OnStart method
AutoResetEvent autoEvent = new AutoResetEvent(true);
while (true)
{
autoEvent.WaitOne();
Thread t = new Thread(MessageQueue.ProcessMessage);
t.Start(autoEvent);
}
What you want is a synchronization timer object. In Win32 this is known as a waitable timer (unfortunately some P/invoke is required, unless I'm mistaken).
Here's what you would do:
Create waitable timer (make sure it's auto-reset).
Set waitable timer with a period of 30 seconds.
Loop:
WaitForSingleObject(waitable timer) with infinite timeout.
Process queue.
If the processing takes more than 30s, the timer will simply remain set until you call WaitForSingleObject on it. Additionally, if the processing takes 20s for example, the timer will be signaled after 10 more seconds.

Why is my code stopping and not returning an exception?

I have some code that starts a couple of threads to let them execute, then uses a while loop to check for the current time passing a set timeout period, or for the correct number of results to have been processed (by checking an int on the class object) (with a Thread.Sleep() to wait between loops)
Once the while loop is set to exit, it calls Abort() on the threads and should return data to the function that calls the method.
When debugging and stepping through the code, I find there can be exceptions in the code running on the separate threads, and in some cases I handle these appropriately, and at other times I don't want to do anything specific.
What I have been seeing is that my code goes into the while loop and the thread sleeps, then nothing is returned from my function, either data or an exception. Code execution just stops completely.
Any ideas what could be happening?
Code sample:
System.Threading.Thread sendThread =
new System.Threading.Thread(new System.Threading.ThreadStart(Send));
sendThread.Start();
System.Threading.Thread receiveThread =
new System.Threading.Thread(new System.Threading.ThreadStart(Receive));
receiveThread.Start();
// timeout
Int32 maxSecondsToProcess = this.searchTotalCount * timeout;
DateTime timeoutTime = DateTime.Now.AddSeconds(maxSecondsToProcess);
Log("Submit() Timeout time: " + timeoutTime.ToString("yyyyMMdd HHmmss"));
// while we're still waiting to receive results & haven't hit the timeout,
// keep the threads going
while (resultInfos.Count < this.searchTotalCount && DateTime.Now < timeoutTime)
{
Log("Submit() Waiting...");
System.Threading.Thread.Sleep(10 * 1000); // 1 minute
}
Log("Submit() Aborting threads"); // <== this log doesn't show up
sendThread.Abort();
receiveThread.Abort();
return new List<ResultInfo>(this.resultInfos.Values);
So, you really shouldn't use the Sleep method on the thread for synchronization purposes. This is what synchronization classes such as ManualResetEvent are for, as well as the Asynchronous Programming Model (IAsyncResult implementations).
A better approach here would be to create a delegate with the signature of the method you want to run asynchronously. Then, assign the method group that is the entry point for the asynchronous operation to an instance of that delegate and call BeginInvoke on the delegate instance.
From there, you would run your loop, expect you would call the overload of WaitOne on the WaitHandle returned by the AsyncWaitHandle property of the IAsyncResult implementation returned by the call to BeginInvoke on the delegate.
This will cause less reliance on the Sleep method (which is bad for synchronization in general).
If you have the option to use .NET 4.0, then you might want to take a look at the Task class in the System.Threading.Tasks namespace as it provides an even better way to handle asynchronous processing, cancellation, and wait timeouts.
Thread.Abort Raises a ThreadAbortException in the thread on which it is invoked
You shouldn't let exceptions escape from your threads ever - you should have exception handling in your threaded object. At the very least there should be a try\catch block around the code in the threaded object.

how do set a timeout for a method

how do set a timeout for a busy method +C#.
Ok, here's the real answer.
...
void LongRunningMethod(object monitorSync)
{
//do stuff
lock (monitorSync) {
Monitor.Pulse(monitorSync);
}
}
void ImpatientMethod() {
Action<object> longMethod = LongRunningMethod;
object monitorSync = new object();
bool timedOut;
lock (monitorSync) {
longMethod.BeginInvoke(monitorSync, null, null);
timedOut = !Monitor.Wait(monitorSync, TimeSpan.FromSeconds(30)); // waiting 30 secs
}
if (timedOut) {
// it timed out.
}
}
...
This combines two of the most fun parts of using C#. First off, to call the method asynchronously, use a delegate which has the fancy-pants BeginInvoke magic.
Then, use a monitor to send a message from the LongRunningMethod back to the ImpatientMethod to let it know when it's done, or if it hasn't heard from it in a certain amount of time, just give up on it.
(p.s.- Just kidding about this being the real answer. I know there are 2^9303 ways to skin a cat. Especially in .Net)
You can not do that, unless you change the method.
There are two ways:
The method is built in such a way that it itself measures how long it has been running, and then returns prematurely if it exceeds some threshold.
The method is built in such a way that it monitors a variable/event that says "when this variable is set, please exit", and then you have another thread measure the time spent in the first method, and then set that variable when the time elapsed has exceeded some threshold.
The most obvious, but unfortunately wrong, answer you can get here is "Just run the method in a thread and use Thread.Abort when it has ran for too long".
The only correct way is for the method to cooperate in such a way that it will do a clean exit when it has been running too long.
There's also a third way, where you execute the method on a separate thread, but after waiting for it to finish, and it takes too long to do that, you simply say "I am not going to wait for it to finish, but just discard it". In this case, the method will still run, and eventually finish, but that other thread that was waiting for it will simply give up.
Think of the third way as calling someone and asking them to search their house for that book you lent them, and after you waiting on your end of the phone for 5 minutes you simply say "aw, chuck it", and hang up. Eventually that other person will find the book and get back to the phone, only to notice that you no longer care for the result.
This is an old question but it has a simpler solution now that was not available then: Tasks!
Here is a sample code:
var task = Task.Run(() => LongRunningMethod());//you can pass parameters to the method as well
if (task.Wait(TimeSpan.FromSeconds(30)))
return task.Result; //the method returns elegantly
else
throw new TimeoutException();//the method timed-out
While MojoFilter's answer is nice it can lead to leaks if the "LongMethod" freezes. You should ABORT the operation if you're not interested in the result anymore.
public void LongMethod()
{
//do stuff
}
public void ImpatientMethod()
{
Action longMethod = LongMethod; //use Func if you need a return value
ManualResetEvent mre = new ManualResetEvent(false);
Thread actionThread = new Thread(new ThreadStart(() =>
{
var iar = longMethod.BeginInvoke(null, null);
longMethod.EndInvoke(iar); //always call endinvoke
mre.Set();
}));
actionThread.Start();
mre.WaitOne(30000); // waiting 30 secs (or less)
if (actionThread.IsAlive) actionThread.Abort();
}
You can run the method in a separate thread, and monitor it and force it to exit if it works too long. A good way, if you can call it as such, would be to develop an attribute for the method in Post Sharp so the watching code isn't littering your application.
I've written the following as sample code(note the sample code part, it works, but could suffer issues from multithreading, or if the method in question captures the ThreadAbortException would break it):
static void ActualMethodWrapper(Action method, Action callBackMethod)
{
try
{
method.Invoke();
} catch (ThreadAbortException)
{
Console.WriteLine("Method aborted early");
} finally
{
callBackMethod.Invoke();
}
}
static void CallTimedOutMethod(Action method, Action callBackMethod, int milliseconds)
{
new Thread(new ThreadStart(() =>
{
Thread actionThread = new Thread(new ThreadStart(() =>
{
ActualMethodWrapper(method, callBackMethod);
}));
actionThread.Start();
Thread.Sleep(milliseconds);
if (actionThread.IsAlive) actionThread.Abort();
})).Start();
}
With the following invocation:
CallTimedOutMethod(() =>
{
Console.WriteLine("In method");
Thread.Sleep(2000);
Console.WriteLine("Method done");
}, () =>
{
Console.WriteLine("In CallBackMethod");
}, 1000);
I need to work on my code readability.
Methods don't have timeouts in C#, unless your in the debugger or the OS believes your app has 'hung'. Even then processing still continues and as long as you don't kill the application a response is returned and the app continues to work.
Calls to databases can have timeouts.
Could you create an Asynchronous Method so that you can continue doing other stuff whilst the "busy" method completes?
I regularly write apps where I have to synchronize time critical tasks across platforms. If you can avoid thread.abort you should. See http://blogs.msdn.com/b/ericlippert/archive/2010/02/22/should-i-specify-a-timeout.aspx and http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation for guidelines on when thread.abort is appropriate. Here are the concept I implement:
Selective execution: Only run if a reasonable chance of success exists (based on ability to meet timeout or likelihood of success result relative to other queued items). If you break code into segments and know roughly the expected time between task chunks, you can predict if you should skip any further processing. Total time can be measured by wrapping an object bin tasks with a recursive function for time calculation or by having a controller class that watches workers to know expected wait times.
Selective orphaning: Only wait for return if reasonable chance of success exists. Indexed tasks are run in a managed queue. Tasks that exceed their timeout or risk causing other timeouts are orphaned and a null record is returned in their stead. Longer running tasks can be wrapped in async calls. See example async call wrapper: http://www.vbusers.com/codecsharp/codeget.asp?ThreadID=67&PostID=1
Conditional selection: Similar to selective execution but based on group instead of individual task. If many of your tasks are interconnected such that one success or fail renders additional processing irrelevant, create a flag that is checked before execution begins and again before long running sub-tasks begin. This is especially useful when you are using parallel.for or other such queued concurrency tasks.

Categories

Resources