我有一个问题。我正在写一个基准测试,我有一个功能,而不是在2秒或大约5分钟后完成(取决于输入数据)。如果执行时间超过3秒,我想停止该功能......
我该怎么做?
非常感谢!
最好的方法是你的函数可以经常检查它的执行时间,以决定停止它需要太长时间。
如果不是这种情况,则在单独的线程中运行该函数。在你的主线程中启动一个3秒计时器。当计时器过去时,使用Thread.Abort()终止单独的线程(当然除非该功能已经结束)。请参阅函数文档中的示例代码和使用前的预撤离。
嗯...,我有同样的问题,在阅读了这里的所有答案和推荐的博客之后,我为此付诸东流,
它让我执行任何带有时间限制的代码块,声明包装器方法
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
您可以使用fork / join模式,在任务并行库中,这是使用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
C#在中间停止函数的最好方法是函数中的return
关键字,但是如何知道何时使用return
关键字在中间停止函数后,它会持续至少3秒?来自Stopwatch
的System.Diagnostics
课程就是答案。这个复杂的函数持续2秒到5分钟(取决于输入数据)逻辑上使用很多循环,甚至可能是递归,所以我的解决方案是,在该函数的第一行代码中,创建一个Stopwatch
的实例使用带有System.Diagnostics
关键字的new
,通过调用Stopwatch类的Start()
函数启动它,并在每个循环和循环中,在开头添加以下代码:
if (stopwatch.ElapsedMilliseconds >= 3000) {
stopwatch.Stop();
// or
stopwatch.Reset();
return;
}
(提示:您可以用手键入一次,将其复制为Ctrl + C,然后将其粘贴到Ctrl + V)。如果该函数使用递归,为了节省内存,请创建秒表全局实例,而不是首先将其创建为本地实例,如果它没有在代码的开头运行,则启动它。你可以用秒表类的IsRunning
知道。之后询问是否经过的时间超过3秒,如果是(true
)停止或重置秒表,并使用return
关键字来停止递归循环,那么函数启动非常好,如果你的函数持续很长时间主要是由于递归不仅仅是循环。这是。正如您所看到的,它非常简单,我测试了这个解决方案,结果表明它有效!亲自尝试一下!
private 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.");
}
在线程中运行此函数并在3秒后终止它或检查此函数内的已用时间(我认为它是循环)。
使用带有hi性能计数器的OS回调,然后杀死你的线程(如果存在)
由于C#和.net框架不是实时环境,因此即使是3秒计数也无法保证。即使你接近那个,你仍然需要打电话给
if(timeSpan > TimeSpan.FromSeconds(3) then goto endindentifier;
在方法中的每次其他调用之前。
所有这一切都是错的所以不,没有可靠的方法从我所知道的那样做。
虽然你可以尝试这个解决方案
但我不会在.net应用程序中做这些事情。