如何为繁忙的方法设置超时+C#。
好的,这里是真正的答案。
...
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
魔法的委托。
然后,使用监视器从LongRunningMethod
向ImpatientMethod
发送消息,以便在完成时通知它,或者如果在一定时间内没有收到消息,则放弃它。
(附注:开玩笑,这不是真正的答案。我知道在.Net中有2^9303种解决方法,特别是剥皮猫的方法。)
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
尽管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();
}
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);
我需要提高我的代码可读性。
C# 中的方法没有超时限制,除非您在调试器中或操作系统认为您的应用程序已经“挂起”。即使如此,处理仍然会继续进行,只要您不杀死应用程序,就会返回响应并且应用程序会继续工作。
对数据库的调用可能会有超时限制。