【发布时间】:2022-02-19 02:59:53
【问题描述】:
背景
我有一个Service 抽象。每个服务都有自己的WorkItem。 WorkItem 能够从一些数据开始。该服务正在限制WorkItem 的执行时间。假设单个工作项最多可能需要 60 秒。在此之后,Service 应该杀死它。
此代码从 .NET Framework 迁移,我创建了一个运行 Start(model) 方法的 Thread 对象。然后代码是这样的:
Thread t = new Thread(workItem.Start, model);
t.start();
if (!t.Join(TimeSpan.FromSeconds(60)))
t.Abort();
Thread.Abort 正在为正在运行的线程注入异常,导致它立即停止。
现在,我将代码移至 dotnet core - 您可能知道,当您调用 Thread.Abort() 时,您会收到以下消息:
System.PlatformNotSupportedException: Thread abort is not supported on this platform.
at System.Threading.Thread.Abort()
at ...
目标
我想将WorkItem 的执行时间限制为特定的时间量。请注意,如果您运行这样的代码行,此限制也应该起作用:
Thread.Sleep(61000); // 61 seconds. should be stop after 60 seconds.
进展
在 dotnet core 世界上,似乎要转到Task 相关解决方案。所以,我想用CancellationToken。但它似乎不可能观看“取消”事件并立即停止。我看到的例子是使用while (!canceled) 循环,它不能停止长时间的操作(比如Thread.Sleep(1000000)。
问题
怎么做才对?
更新
我写了这个示例代码:
public static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock)
{
try
{
Task task = Task.Factory.StartNew(() => codeBlock());
if (!task.Wait(timeSpan))
{
// ABORT HERE!
Console.WriteLine("Time exceeded. Aborted!");
}
return task.IsCompleted;
}
catch (AggregateException ae)
{
throw ae.InnerExceptions[0];
}
}
还有这个Main 文件:
public static void Main(string[] args)
{
bool Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(2000), () =>
{
Console.WriteLine("start");
Thread.Sleep(3000);
Console.WriteLine("end");
});
Console.WriteLine($"Completed={Completed}");
Console.ReadLine();
}
预期:“end”不会打印到屏幕上。实际:打印“结束”。有没有可以杀死Task的替代方法?
【问题讨论】:
-
试试Task.Delay而不是
Thread.Sleep -
您知道要正确执行此操作,您只需不中止线程...从一开始就不是好主意。可能应该作为 stackoverflow.com/questions/39243016/… 的副本关闭
-
@H.G.Sandhagen 它不会帮助处理实际上长时间占用 CPU 而不是休眠的代码......或者使用同步网络调用......
-
@H.G.Sandhagen -
Thread.Sleep只是一个例子。我可以想到其他不支持异步模型的示例。再比如:下载WebClient的文件,服务器真的很慢,所以耗时太长(超过限制)。 -
@AlexeiLevenkov - 不确定它是否“聪明”的想法。当您处理导致不同执行时间的不同类型的数据时,这是需要的。
Thread.Abort的替代方法是为每个WorkItem创建一个单独的进程,如果运行时间过长,则将其终止 - 对我来说听起来会消耗太多资源。
标签: c# multithreading .net-core .net-5 thread-abort