在单独的ThreadPool中执行某些后台任务,以避免饿死于在主线程中执行的关键任务

问题描述 投票:1回答:1

在单独的ThreadPool中执行某些后台任务(非线程),以避免饿死于在主线程中执行的关键任务(非线程)

我们的场景

我们托管一个高容量的WCF Web服务,该服务在逻辑上具有以下代码:

void WcfApiMethod()
{
   // logic

   // invoke other tasks which are critical
   var mainTask = Task.Factory.StartNew(() => { /* important task */ });
   mainTask.Wait();

   // invoke background task which is not critical
   var backgroundTask = Task.Factory.StartNew(() => { /* some low-priority background action (not entirely async) */ });
   // no need to wait, as this task is best effort. Fire and forget

   // other logic
}

// other APIs

现在,在某些情况下,低优先级后台任务可能会花费更长的时间(〜30秒),例如,检测到SQL连接问题,DB性能问题,Redis缓存问题等,这些都会使这些背景线程延迟,这意味着由于高容量,“总待处理任务数”将增加。

这会创建一个方案,在该方案中,较新的API执行无法安排高优先级任务,因为有许多后台任务在排队。

我们尝试过的解决方案

  1. 将TaskCreationOptions.LongRunning添加到高优先级任务将立即执行它。但是,这对我们来说不是解决方案,因为在系统中到处都有很多任务被调用,因此我们无法使它们在任何地方都可以长时间运行。同样,WCF对传入API的处理将依赖于.NET线程池,该线程池现在处于饥饿状态。

  2. 通过信号量创建短路的低优先级后台任务。仅在系统具有处理线程的能力时才产生线程(检查先前创建的线程是否已退出)。如果没有,那就不要产生线程。例如,由于问题(例如DB perf问题),IO等待中有约10,000个后台线程(非异步),这可能会导致主.net线程池中的线程不足。在这种特定情况下,我们可以添加一个信号量以将创建限制为100个,因此,如果卡住了100个任务,则首先不会创建第101个任务。

询问替代解决方案

是否有一种方法可以在“自定义线程/线程池”而不是默认的.NET线程池上专门生成“任务”。这是针对我提到的后台任务,因此,如果它们延迟了,它们不会使整个系统崩溃。可能会被覆盖并创建一个自定义TaskScheduler传递给Task.Factory.StartNew(),因此,创建的任务将不在默认的.NET线程池上,而是在其他一些自定义池上。

c# multithreading async-await task task-parallel-library
1个回答
0
投票
内置ConcurrentExclusiveSchedulerPair.ConcurrentScheduler可用于实现此目的。

对于上述情况,以下代码限制了后台线程破坏应用程序/防止线程匮乏。

{ // fire and forget background task var task = Task.Factory.StartNew( () => { // background threads } , CancellationToken.None , TaskCreationOptions.None , concurrentSchedulerPair.ConcurrentScheduler); } private static ConcurrentExclusiveSchedulerPair concurrentSchedulerPair = new ConcurrentExclusiveSchedulerPair( TaskScheduler.Default, maxConcurrencyLevel: 100);

关于使用TaskScheduler.Default和maxConcurrencyLevel:100参数的注意事项,例如,您使用此limited-conc-scheduler创建10000个任务,并尝试立即使用'default-scheduler'产生另一个线程,除非所有创建了100个线程。如果尝试使用maxConcurrencyLevel:10,则立即实例化所有10个线程后,将立即生成新的线程且不会阻塞。 

感谢@Theodor Zoulias提供的指针。

© www.soinside.com 2019 - 2024. All rights reserved.