How to stop the method from running after a certain time?

I need to stop the method execution if it has not completed within a limited period of time.

To do this, I can use the Thread.Abort method as follows:

 void RunWithTimeout(ThreadStart entryPoint, int timeout) { var thread = new Thread(() => { try { entryPoint(); } catch (ThreadAbortException) { } }) { IsBackground = true }; thread.Start(); if (!thread.Join(timeout)) thread.Abort(); } 

Given that I'm using .NET 3.5, is there a better way?

Edit: after the comments, here is my entryPoint , but I'm looking for a good way for any entryPoint .

 void entryPoint() { // I can't use ReceiveTimeout property // there is not a ReceiveTimeout for the Compact Framework socket.Receive(...); } 
+4
source share
2 answers

The answer depends on the "work". If work is something that can be safely stopped (i.e. not an I / O blocking operation) - use Backgroundworker.CancelAsync(...)

If you need to cut hard, I would think about using Process , in which case the Aborting process will be cleaner, and process.WaitForExit(timeout) is your friend.

The recommended TPL is great, but unfortunately does not exist in .Net 3.5.

EDIT: You can use Reactive Extensions to follow Ian de Waan's suggestion.

Here is my "action timeout" - this is mostly here so others can comment:

  public static bool WaitforExit(this Action act, int timeout) { var cts = new CancellationTokenSource(); var task = Task.Factory.StartNew(act, cts.Token); if (Task.WaitAny(new[] { task }, TimeSpan.FromMilliseconds(timeout)) < 0) { // timeout cts.Cancel(); return false; } else if (task.Exception != null) { // exception cts.Cancel(); throw task.Exception; } return true; } 

EDIT : Apparently, this is not exactly what the OP wanted. Here is my attempt to create a cancellable socket receiver:

 public static class Ext { public static object RunWithTimeout<T>(Func<T,object> act, int timeout, T obj) where T : IDisposable { object result = null; Thread thread = new Thread(() => { try { result = act(obj); } catch {} // this is where we end after timeout... }); thread.Start(); if (!thread.Join(timeout)) { obj.Dispose(); thread.Join(); } return result; } } class Test { public void SocketTimeout(int timeout) { using (var sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { Object res = Ext.RunWithTimeout(EntryPoint, timeout, sock); } } private object EntryPoint(Socket sock) { var buf = new byte[256]; sock.Receive(buf); return buf; } } 
+8
source

Thread.Abort is usually a bad solution . You should use a flag indicating whether the operation is canceled and check it inside your entryPoint function.

  class Program { static void Main(string[] args) { RunWithTimeout((token) => { Thread.Sleep(2000); if (token.Cancel) { Console.WriteLine("Canceled"); } }, 1000); Console.ReadLine(); } private class Token { public bool Cancel { get; set; } } static void RunWithTimeout(Action<Token> entryPoint, int timeout) { Token token = new Token(); var thread = new Thread(() => entryPoint(token)) { IsBackground = true }; thread.Start(); if (!thread.Join(timeout)) token.Cancel = true; } } 
+4
source

Source: https://habr.com/ru/post/1444675/


All Articles