I have a server application which needs to schedule the deferred execution of method(s). In other words, mechanism to run a method using a thread in ThreadPool after a certain period of time.
void ScheduleExecution (int delay, Action someMethod){
//How to implement this???
}
//At some other place
//MethodX will be executed on a thread in ThreadPool after 5 seconds
ScheduleExecution (5000, MethodX);
Please suggest an efficient mechanism to achieve above. I would prefer to avoid frequently creating new objects since above activity is likely to happen A LOT on server. Also the accuracy of call is important, i.e. while MethodX being executed after 5200 msec is fine but being executed after 6000 msec is a problem.
Thanks in advance...
You could use the RegisterWaitForSingleObject method. Here's an example:
public class Program
{
static void Main()
{
var waitHandle = new AutoResetEvent(false);
ThreadPool.RegisterWaitForSingleObject(
waitHandle,
// Method to execute
(state, timeout) =>
{
Console.WriteLine("Hello World");
},
// optional state object to pass to the method
null,
// Execute the method after 2 seconds
TimeSpan.FromSeconds(2),
// Execute the method only once. You can set this to false
// to execute it repeatedly every 2 seconds
true);
Console.ReadLine();
}
}
Related
I see a lot of options for canceling a long-running operation in C#, but each example seems to talk about cancelling parallel (multithreaded) operations or are overly-simple examples, or involve periodically polling for whether a request to cancel the operation was submitted. I don't think that will work here.
I have a method BuildZipFile() which, for now, takes no arguments, but I suspect might need a CancellationToken argument. Calling this method does the following. BuildZipFile() blocks; execution on the thread doesn't resume until it's done with its work.
Files are extracted and added to a zip file. This operation is so quick that I don't want it to be cancelable. If the user requests a cancel, it should ignore the request until the operation is complete, and then skip the rest of BuildZipFile() and return (or throw an exception; doesn't matter).
Files are processed using something called a "pipeline." This operation does take a long time and the user should be able to cancel it. To start this processing, BuildZipFile() calls a non-blocking method Start() on the pipeline. A pipeline raises Done when it's done with its work, so I use an AutoResetEvent to block the method until I hear that event, and then release the block.
Some more operations similar to item #1: quick-running operations that should not support cancelling.
Here's an overly-simplified implementation:
public void BuildZipFile()
{
// single-threaded operation that is quick and can't be canceled
DoQuickUncancelableThings();
// and now a long-running operation that the user SHOULD be able to cancel;
// it must be possible to interrupt the AutoResetEvent
var pipeline = GimmeAPipeline();
var reset = new AutoResetEvent(false);
// when the pipeline raises Done, stop blocking the method and resume execution
pipeline.Done += () => reset.Set();
// define the work to be done
ThreadPool.QueueUserWorkItem(state => pipeline.Start());
// call pipeline.Start() and block the thread until pipeline.Done is raised
reset.WaitOne();
// ...and more quick operations that can't be canceled
DoMoreQuickUncancelableThings();
}
Note that in reality, that middle block of code exists in another class which this one calls.
I can stop the pipeline in this method by calling pipeline.Stop() which will indirectly raise the Done event once the request to stop it was handled.
So, how can I modify BuildZipFile() to support user cancellation? My instinct is to add support for catching an OperationCanceledException, but that would allow those quick operations to cancel too, wouldn't it? And, I can't poll for a cancellation request unless I'm missing something because I'm waiting for that Done event from pipeline to be raised, and the last thing I want to do is poll using a timer to interrupt it.
I have no issues with modifying BuildZipFile() to become non-blocking, but the steps within it are very linear. Step #2 can't even start until step #1 is done; the process can't be made parallel. I cannot change how pipelines work; they must remain asynchronous and raise events when they're done.
I'm using .NET 4.5 in a Windows Forms application so I can use pretty much any framework feature I need.
I think you should use Tasks to do want you want.
Check this msdn article,it is very usefull
http://msdn.microsoft.com/en-us/library/dd537609(v=vs.110).aspx
Here is a full example in a console application
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
class Program
{
static CancellationTokenSource tokenSource2;
static CancellationToken ct;
static void Main(string[] args)
{
tokenSource2 = new CancellationTokenSource();
ct = tokenSource2.Token;
Task myTask = new Task(BuildZipFile);
myTask.Start();
Console.WriteLine("Press enter to cancel");
Console.ReadLine();
tokenSource2.Cancel();
Console.ReadLine();
}
public static void BuildZipFile()
{
Task quick1 = new Task(DoQuickUncancelableThings);
quick1.ContinueWith(ant => DoLongRunnignThings(), ct).ContinueWith(ant => DoMoreQuickUncancelableThings());
quick1.Start();
}
private static void DoMoreQuickUncancelableThings()
{
Console.WriteLine("Q2");
}
private static void DoLongRunnignThings()
{
for (int i = 0; i < 10; i++)
{
System.Threading.Thread.Sleep(1000);
ct.ThrowIfCancellationRequested();
}
Console.WriteLine("Long ended");
}
private static void DoQuickUncancelableThings()
{
Console.WriteLine("Q1");
}
}
}
I have a program where I let the user create several functions and once he creates all the functions I run them every x milliseconds. In other words I have something like:
// functionsToExecute is of type = List<Action>
// x = some integer
while(true){
foreach(Action action in functionsToExecute)
{
action();
}
Thread.Sleep(x);
}
Now I will like for the user to decide how long to wait per function. For example if the user creates 2 functions he might want the first function to run every 500 milliseconds the next one every 1500. I was thinking about creating two threads for this scenario and then have the same implementation. But what if the user creates 50 functions? I will need 50 threads!
In short I will like to execute x number of Actions each every n milliseconds... What will be the best way to create such algorithm? For example if I have 3 Actions I will like to execute the first action every 200 milliseconds, the next one every 500 milliseconds and the last one every 1000 milliseconds.
Maybe I need something similar to the SetTimout function in javascript
If you're using .NET 4.5 and your code is not time-critical, then you can easily do this with the Task Parallel Library:
static Task Repeat (List<Action> actions, CancellationToken token, int delay)
{
var tasks = new List<Task> ();
var cts = CancellationTokenSource.CreateLinkedTokenSource (token);
foreach (var action in actions) {
var task = Task.Factory.StartNew (async () => {
while (true) {
cts.Token.ThrowIfCancellationRequested ();
await Task.Delay (delay, cts.Token).ConfigureAwait (false);
action ();
}
});
tasks.Add (task);
}
return Task.WhenAll (tasks);
}
Ideally, you should also make your actions async to properly support cancellation.
The .NET runtime automatically takes care of thread scheduling, but there's no guarantee that your action will be executed after exactly the requested timeout. It will be executed after at least that time has elapsed and there's an idle thread available.
i would consider using a ThreadPool (walkthrough). Create each thread to process and have it repeat based on the timeout they're looking for. You can also store the ManualResetEvent for when you need the thread(s) to stop.
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.
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.
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.