我有一个问题。我正在编写一个基准测试,并且有一个函数,该函数完成时间有两种情况,一种是2秒钟,另一种是大约5分钟(取决于输入数据)。我想在执行超过3秒钟时停止该函数...
我该怎么做呢?
非常感谢!
我有一个问题。我正在编写一个基准测试,并且有一个函数,该函数完成时间有两种情况,一种是2秒钟,另一种是大约5分钟(取决于输入数据)。我想在执行超过3秒钟时停止该函数...
我该怎么做呢?
非常感谢!
好的,我也有同样的问题,在阅读了这里和参考博客中的所有答案后,我选择了这个方案:
它允许我在限定时间内执行任何代码块,声明包装方法。
public static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock)
{
try
{
Task task = Task.Factory.StartNew(() => codeBlock());
task.Wait(timeSpan);
return task.IsCompleted;
}
catch (AggregateException ae)
{
throw ae.InnerExceptions[0];
}
}
然后使用它来包装任何像这样的代码块
// code here
bool Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(1000), () =>
{
//
// Write your time bounded code here
//
});
//More code
Task task = new Task(codeBlock); task.Wait(timeSpan); task.Start(); return task.IsCompleted;
的代码,因为使用你现在的代码,你是在启动方法并告诉它等待x次。但实际上,分配任务、等待并启动任务才是更好的方法。 - Lost_In_Libraryprivate static int LongRunningMethod()
{
var r = new Random();
var randomNumber = r.Next(1, 10);
var delayInMilliseconds = randomNumber * 1000;
Task.Delay(delayInMilliseconds).Wait();
return randomNumber;
}
而
var task = Task.Run(() =>
{
return LongRunningMethod();
});
bool isCompletedSuccessfully = task.Wait(TimeSpan.FromMilliseconds(3000));
if (isCompletedSuccessfully)
{
return task.Result;
}
else
{
throw new TimeoutException("The function has taken longer than the maximum time allowed.");
}
这对我很有用!
来源:https://jeremylindsayni.wordpress.com/2016/05/28/how-to-set-a-maximum-time-to-allow-a-c-function-to-run-for/return
关键字,但如何知道何时使用return
关键字来在至少持续3秒后中断函数?System.Diagnostics
的Stopwatch
类是答案。这个持续时间在2秒到5分钟之间(取决于输入数据)的复杂函数逻辑上使用了许多循环,甚至可能会使用递归,因此我的解决方案是,在该函数的第一行代码中,使用new
关键字创建Stopwatch
实例,并通过调用Stopwatch类的Start()
函数启动它,在每个循环和循环开始时添加以下代码:if (stopwatch.ElapsedMilliseconds >= 3000) {
stopwatch.Stop();
// or
stopwatch.Reset();
return;
}
(提示:您可以手动输入一次,复制Ctrl + C,然后只需粘贴Ctrl + V即可)。如果该函数使用递归,则为了节省内存,在代码开头将Stopwatch全局实例化而不是作为本地实例化,并在代码开头开始运行它。您可以使用Stopwatch类的IsRunning
来确定这一点。之后询问经过的时间是否超过3秒钟,如果是(true
),则停止或重置Stopwatch,并使用return
关键字停止递归循环,非常适合使用递归而持续时间较长的函数。就是这样。正如您所看到的,这非常简单,我测试了这种解决方案,结果显示它确实有效!您也可以尝试一下!
您可以使用分支/合并模式,在任务并行库中,这是通过Task.WaitAll()实现的。
using System.Threading.Tasks;
void CutoffAfterThreeSeconds() {
// start function on seperate thread
CancellationTokenSource cts = new CancellationTokenSource();
Task loop = Task.Factory.StartNew(() => Loop(cts.Token));
// wait for max 3 seconds
if(Task.WaitAll(new Task[]{loop}, 3000)){
// Loop finished withion 3 seconds
} else {
// it did not finish within 3 seconds
cts.Cancel();
}
}
// this one takes forever
void Loop() {
while (!ct.IsCancellationRequested) {
// your loop goes here
}
Console.WriteLine("Got Cancelled");
}
这将启动另一个任务在单独的线程上,然后等待3000毫秒以便完成。如果在超时时间内完成,则返回true,否则返回false,所以您可以用它来决定接下来做什么。
您可以使用CancellationToken与其他线程通信,告诉它结果不再需要,以便优雅地停止。
祝好 Gert-Jan
可以在单独的线程中执行函数,并使用Thread.Join(millisecondsTimeout)限制其执行:
using System.Threading;
Thread workThread = new Thread(DoFunc);
workThread.Start(param);
if (!workThread.Join(3000))
{
// DoFunc() took longer than 3 seconds. Thread was aborted
}
private void DoFunc(object param)
{
// do some long work
}
因为C#和.net框架不是实时环境,你无法保证哪怕是3秒的计数。 即使你接近这个时间,你仍然需要在方法中的每次调用之前调用if(timeSpan > TimeSpan.FromSeconds(3) then goto endindentifier;
。
所有这些都是错误的,所以我认为没有可靠的方法可以做到。虽然你可以尝试这个解决方案。
但我不会在 .net 应用程序中做这样的事情。