Last active
February 15, 2024 08:17
-
-
Save xdedss/ed9fb58ce31b3e3b165774b035ce65d3 to your computer and use it in GitHub Desktop.
An attempt to run actions with timeout in C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Threading; | |
| public class TimeoutAction | |
| { | |
| private Thread timerThread; | |
| private Thread mainThread; | |
| private AutoResetEvent timerStartEvent = new AutoResetEvent(false); | |
| private AutoResetEvent timerPreparedEvent = new AutoResetEvent(false); | |
| long timeoutTicks; | |
| object locker = new object(); | |
| public TimeoutAction() | |
| { | |
| timerThread = new Thread(() => { | |
| while (true) // this timer thread will be reused so that there is no need to creat a new one each time. | |
| { | |
| timerStartEvent.WaitOne(); // wait for next action | |
| try | |
| { | |
| timerPreparedEvent.Set(); // notify the main thread | |
| Thread.Sleep(15); // minimum resolution | |
| while (DateTime.Now.Ticks < timeoutTicks) | |
| { | |
| Thread.Sleep(5); | |
| } | |
| Thread.Sleep(0); | |
| lock (locker) // perhaps this is necessary to prevent two threads from fighting against each other | |
| { | |
| mainThread.Abort(); | |
| } | |
| } | |
| catch (ThreadInterruptedException) | |
| { | |
| // this means that the action in the main thread is completed | |
| } | |
| } | |
| }); | |
| timerThread.Start(); | |
| } | |
| public void Run(Action action, int millisecondsTimeout) | |
| { | |
| mainThread = Thread.CurrentThread; // whichever thread that calls this method. doesn't have to be the real main thread | |
| timeoutTicks = DateTime.Now.Ticks + millisecondsTimeout * 10000L; // 1ms = 10000Ticks | |
| timerStartEvent.Set(); // notify the timer thread | |
| timerPreparedEvent.WaitOne(1000); // wait for the timer thread to be ready | |
| try | |
| { | |
| action(); | |
| } | |
| catch (ThreadAbortException) // timeout! | |
| { | |
| Thread.ResetAbort(); | |
| throw new TimeoutException(); | |
| } | |
| catch (Exception ex) | |
| { | |
| lock (locker) | |
| { | |
| timerThread.Interrupt(); | |
| } | |
| throw new Exception("Exception during execution: ", ex); | |
| } | |
| lock (locker) | |
| { | |
| timerThread.Interrupt(); | |
| } | |
| } | |
| ~TimeoutAction() | |
| { | |
| if (timerThread != null) | |
| { | |
| timerThread.Abort(); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment