如果命令执行时间过长,请取消执行
本文关键字:取消 执行 命令 执行时间 如果 | 更新日期: 2023-09-27 18:30:11
我目前正在开发一个软件,该软件使用来自不同部门的程序集
我从这个程序集中调用一个方法,如下所示:
using (var connection = (IConnection) Factory.GetObject(typeof (IConnection)))
代码过去运行得非常好。但在最后几分钟,当我试图启动程序时,它似乎什么都没做。在调试时按下暂停键,我发现它"卡"在了上面的行
我猜他们只是在做一些维护或其他什么,但这不是重点
所以我认为如果程序没有启动,告诉用户出了什么问题会很好。像这样简单的东西
MessageBox.Show("Could not connect", "Connection Error");
然后关闭程序。我的问题是:
如何在设定的时间后终止命令的执行并跳转到其他地方
我的猜测是将它移动到一个单独的线程,然后让调用线程休眠几秒钟,然后如果还没有完成,它就会处理多余的线程。但对我来说,这似乎真的很肮脏,必须有更好的方法。
您的问题可以分为两部分:
- 如何终止命令的执行
唯一的方法是中止线程但不要这样做。没有保证和安全的方法。有像Thread.Interrupt和Thread.Artrt这样的方法可以唤醒线程。但只有当线程处于WaitSleepJoin状态并且挂在托管代码中时,它们才会工作。
看起来你已经知道了。但是再一次,如果程序集中的某个东西无限地挂起了代码的执行,那么线程可能就"消失"了。所以你应该关闭这个程序是对的。
- 。。。跳到别的地方
好的方法是使用TPL和异步模型。这里有一个扩展方法来结束任何任务,并在超时后过期。
public static async Task TimeoutAfter(this Task task, int millisecondsTimeout)
{
if (task == await Task.WhenAny(task, Task.Delay(millisecondsTimeout)))
await task;
else
throw new TimeoutException();
}
然后使用
try
{
using (var result = await Task.Run(() => (IConnection)Factory.GetObject(typeof(IConnection))).TimeoutAfter(1000))
{
...
}
}
catch (TimeoutException ex)
{
//timeout
}
在这里您可以找到更多信息
一种不需要额外库或扩展方法的简单方法:
using ( var task = new Task<IConnection>( () => Factory.GetObject( typeof( IConnection ) ) ) )
{
task.Start();
if( !task.Wait( timeoutMilliseconds ) )
{
throw new TimeoutException();
}
IConnection result = task.Result;
}
Task.Wait
执行您想要的操作,因为如果返回false(任务未及时完成),您可以抛出异常
如果你有一个不返回东西的Action,那就更简单了:
if ( !Task.Run( action ).Wait( timeoutMilliseconds ) )
{
throw new TimeoutException();
}
其中CCD_ 2是一些CCD_。
如果没有实现本机超时,最简单的方法是用一个单独的线程来加载它,正如您所提到的。虽然这听起来很脏,但它就像(使用Rx):
Task<IConnection> connectionTask = Observable.Start(() => Factory.GetObject(typeof (IConnection)), Scheduler.Default).Timeout(TimeSpan.FromSeconds(20)).ToTask());
using (var connection = connectionTask.Result)
{
...
}
如果不希望Scheduler
在线程池上运行,可以对其进行调整。如果Factory.GetObject
调用的时间超过20秒,它将抛出一个TimeoutException
。
您可以使用CancellationTokenSource设置操作的超时
var timeoutCts = new CancellationTokenSource();
try
{
timeoutCts.CancelAfter(300000); // Cancel after 5 minutes
// ... run your long term operation
}
catch (OperationCanceledException ex)
{
// Handle the timeout
}
请参阅Microsoft 的此文档
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Task t = Task.Run(() =>
{
Random rnd = new Random();
long sum = 0;
int n = 5000000;
for (int ctr = 1; ctr <= n; ctr++)
{
int number = rnd.Next(0, 101);
sum += number;
}
Console.WriteLine("Total: {0:N0}", sum);
Console.WriteLine("Mean: {0:N2}", sum / n);
Console.WriteLine("N: {0:N0}", n);
});
TimeSpan ts = TimeSpan.FromMilliseconds(150);
if (!t.Wait(ts))
Console.WriteLine("The timeout interval elapsed.");
}
}