如何为busy方法+ C#设置超时。
答案 0 :(得分:12)
好的,这是真正的答案。
...
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#的两个最有趣的部分。首先,要异步调用该方法,请使用具有fancy-pants BeginInvoke
魔法的委托。
然后,使用监视器将LongRunningMethod
的消息发送回ImpatientMethod
,让它知道该消息何时完成,或者是否在一定时间内没有收到消息,放弃吧。
(p.s.-开玩笑说这才是真正的答案。我知道有2 ^ 9303种皮肤猫的方法。尤其是.Net)
答案 1 :(得分:7)
除非您更改方法,否则不能这样做。
有两种方法:
最明显的,但不幸的是错误,你可以得到的答案是“只需在线程中运行该方法并在运行太长时间时使用Thread.Abort”。
唯一正确的方法是让方法以这样一种方式进行合作:当它运行的时间过长时,它会进行干净的退出。
还有第三种方法,你在一个单独的线程上执行该方法,但在等待它完成之后,这需要很长时间才能完成,你只需说“我不会等待它完成,但只是丢弃它“。在这种情况下,该方法仍将运行,并最终完成,但等待它的其他线程将放弃。
想想第三种方式,就是打电话给别人,并要求他们在房子里搜索你借给他们的那本书,然后在等待电话结束5分钟后,你只需说“哇,把它扔掉”,然后挂起来。最终,其他人会找到这本书并重新打电话,只是注意到你不再关心结果。
答案 2 :(得分:3)
虽然MojoFilter's answer很好,但如果&#34; LongMethod&#34;可能会导致泄漏。冻结。如果你对结果不感兴趣,你应该中止操作。
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();
}
答案 3 :(得分:3)
这是一个古老的问题,但它现在有一个更简单的解决方案,现在还没有:任务!
以下是示例代码:
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
答案 4 :(得分:2)
您可以在单独的线程中运行该方法,并监视它并在其工作时间过长时强制退出。一个好方法,如果你可以这样调用它,就是在Post Sharp中为方法开发一个属性,这样看守代码就不会乱丢你的应用程序。
我已经将以下内容编写为示例代码(请注意示例代码部分,它可以工作,但可能会遇到多线程问题,或者如果有问题的方法捕获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);
我需要处理我的代码可读性。
答案 5 :(得分:0)
方法在C#中没有超时,除非您在调试器或操作系统中认为您的应用已“挂起”。即使这样,处理仍然继续,只要您不杀死应用程序,就会返回响应并且应用程序继续工作。
调用数据库可能会超时。
答案 6 :(得分:0)
你可以创建一个Asynchronous Method,以便在“忙碌”方法完成时继续做其他事情吗?
答案 7 :(得分:0)
我经常编写应用程序,我必须跨平台同步时间关键任务。如果你可以避免thread.abort你应该。有关何时适合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/cancellation。以下是我实施的概念: