如何做设置超时的方法(how do set a timeout for a method)

2019-07-17 18:09发布

如何做设置一个繁忙的方法+ C#超时。

Answer 1:

好吧,这里是真正的答案。

...

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.
  }
}

   ...

这种结合了两个使用C#中最有趣的部分。 首先,异步调用该方法,使用具有花哨的裤子委托BeginInvoke魔法。

然后,使用一台显示器从消息发送LongRunningMethodImpatientMethod让它知道当它这样做,或者如果它不是来自它在一定的时间听到,只是放弃了它。

(PS-只是开玩笑这是真正的答案。我知道有2 ^ 9303的方式皮肤猫,尤其是在.NET)



Answer 2:

你不能这样做,除非你改变的方法。

有两种方法:

  1. 该方法是建立在其本身的尺寸了多长时间运行的时间,如果超过某个阈值,然后返回过早这种方式。
  2. 该方法是建立在它监控变量/事件,说:“当这个变量设置,请退出”这样的方式,然后你有另一个线程测量在第一种方法所花费的时间,然后设置变量时,经过时间已经超过某个阈值。

最明显的,但不幸的是错的,回答您可以在这里“只是运行一个线程的方法和使用Thread.Abort的时候它已经跑了太久”。

唯一正确的方法是对的方法以这样的方式,当它已经运行过久会做一个干净的退出合作。

还有第三种方式,在那里你执行一个单独的线程的方法,但等待它完成,而要做到这时间太长,你简单地说“我不会等待它完成,但刚过丢弃它。” 在这种情况下,该方法将继续运行,并最终完成,但等待它的其他线程就干脆放弃。

想想第三条道路作为呼叫某人,并要求他们寻找他们家的那本书你借给他们,你在你的手机端等待5分钟后,你简单地说“噢,不干了”,并挂断电话。 最后,其他的人会发现这本书,回到了电话,才发现,你不再关心的结果。



Answer 3:

虽然MojoFilter的答案是好的,它可能会导致泄漏,如果“LongMethod”冻结。 如果你不感兴趣的结果了,那么你应该放弃操作。

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();
}


Answer 4:

这是一个老问题,但它现在有一个简单的解决方案,这是不可用,则:任​​务!

下面是一个示例代码:

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


Answer 5:

您可以运行在一个单独的线程的方法,并监控它,迫使它退出,如果它工作太长时间。 一个好方法,如果你可以调用它是这样,将制定在该方法的属性后夏普所以看代码不乱扔垃圾应用程序。

我已经写了下面的示例代码(注意,示例代码的一部分,它的工作原理,但可以从多线程遭受的问题,或者如果有问题的方法捕获的ThreadAbortException会打破它):

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();
}

用下面的调用:

CallTimedOutMethod(() =>
{
    Console.WriteLine("In method");
    Thread.Sleep(2000);
    Console.WriteLine("Method done");
}, () =>
{
    Console.WriteLine("In CallBackMethod");
}, 1000);

我需要在我的代码的可读性工作。



Answer 6:

方法没有在C#超时,除非你在调试器或操作系统相信您的应用程序已经“挂”。 即使是这样处理仍继续只要你不杀返回响应的应用程序和应用程序继续工作。

调用数据库可以有超时。



Answer 7:

你可以创建一个异步方法 ,这样就可以继续做其他的东西,而“忙”的方法完成?



Answer 8:

我经常写的应用程序在那里我有跨平台同步时间关键的任务。 如果你能避免Thread.Abort的你应该。 见http://blogs.msdn.com/b/ericlippert/archive/2010/02/22/should-i-specify-a-timeout.aspx和http://www.interact-sw.co.uk/iangblog / 2004/11/12 /注销的时候Thread.Abort的是适当的准则。 下面是我实现的概念:

  • 选择性执行:只有当一个合理的成功机会存在(基于满足超时或相对于其他排队的项目成功结果的可能性的能力)上运行。 如果断码成段,知道大致的任务块之间的预期时间,可以预测,如果你要跳过任何进一步的处理。 总时间可通过与用于时间计算的递归函数包装对象仓任务或通过具有手表工人知道预期等待时间的控制器类来测量。
  • 选择成为孤儿:只有等待回报,如果成功的合理的机会存在。 索引任务在托管队列中运行。 超过他们的超时或风险,从而导致其他超时任务孤儿和一个空的记录代替他们返回。 更长的运行任务可以被包裹在异步调用。 见例如异步调用包装: http://www.vbusers.com/codecsharp/codeget.asp?ThreadID=67&PostID=1
  • 有条件的选择:类似于选择性执行,但基于群体的,而不是单独的任务。 如果你的很多任务都互连,使得一个成功或失败提供了额外的处理无关,创建执行开始之前被检查并再次之前长时间运行的子任务开始的标志。 当您使用的Parallel.For或其他类似的排队并发任务,这是特别有用的。


文章来源: how do set a timeout for a method