how do set a timeout for a method

前端 未结 8 1271
情书的邮戳
情书的邮戳 2020-12-25 15:10

how do set a timeout for a busy method +C#.

相关标签:
8条回答
  • 2020-12-25 15:48

    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
    
    0 讨论(0)
  • 2020-12-25 15:49

    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.
    0 讨论(0)
  • 2020-12-25 15:51

    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();
    }
    
    0 讨论(0)
  • 2020-12-25 15:55

    Could you create an Asynchronous Method so that you can continue doing other stuff whilst the "busy" method completes?

    0 讨论(0)
  • 2020-12-25 15:57

    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.

    0 讨论(0)
  • 2020-12-25 16:04

    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.

    0 讨论(0)
提交回复
热议问题