У меня есть код, который запускает тысячи URL-адресов через стороннюю библиотеку. Иногда метод в библиотеке зависает, который занимает поток. Через некоторое время все потоки заняты процессами, которые ничего не делают, и он останавливается.Как обрабатывать потоки, зависающие при использовании SemaphoreSlim
Я использую команду SemaphoreSlim
для управления добавлением новых потоков, чтобы у меня было оптимальное количество выполняемых задач. Мне нужен способ определить задачи, которые выполнялись слишком долго, а затем убить их, но также освободить поток от SemaphoreSlim
, чтобы можно было создать новую задачу.
Я борюсь с подходом здесь, поэтому я сделал несколько тестовых кодов, которые имитируют то, что я делаю. Он создает задачи, которые имеют 10% -ный шанс повесить так быстро, что все потоки повесили.
Как я должен проверять их и убивать их?
Вот код:
class Program
{
public static SemaphoreSlim semaphore;
public static List<Task> taskList;
static void Main(string[] args)
{
List<string> urlList = new List<string>();
Console.WriteLine("Generating list");
for (int i = 0; i < 1000; i++)
{
//adding random strings to simulate a large list of URLs to process
urlList.Add(Path.GetRandomFileName());
}
Console.WriteLine("Queueing tasks");
semaphore = new SemaphoreSlim(10, 10);
Task.Run(() => QueueTasks(urlList));
Console.ReadLine();
}
static void QueueTasks(List<string> urlList)
{
taskList = new List<Task>();
foreach (var url in urlList)
{
Console.WriteLine("{0} tasks can enter the semaphore.",
semaphore.CurrentCount);
semaphore.Wait();
taskList.Add(DoTheThing(url));
}
}
static async Task DoTheThing(string url)
{
Random rand = new Random();
// simulate the IO process
await Task.Delay(rand.Next(2000, 10000));
// add a 10% chance that the thread will hang simulating what happens occasionally with http request
int chance = rand.Next(1, 100);
if (chance <= 10)
{
while (true)
{
await Task.Delay(1000000);
}
}
semaphore.Release();
Console.WriteLine(url);
}
}
Вы не должны убивать задачи в первую очередь. Используйте некоторый механизм сотрудничества для прерывания операции, чтобы он мог освободить семафор, за который он несет ответственность. К сожалению, на ваш вопрос не хватает всех деталей, необходимых для понимания самой реализации задачи, но, вообще говоря, при работе с сетевым вводом-выводом (например, HTTP-запросами) у вас не должно быть активного потока ... вы должны использовать .NET асинхронные API для выполняемых операций. –
«Как я должен быть ... убивать их?» - Вы не должны - убивать нити плохо плохо. Если ваша сторонняя библиотека рушится, вам может потребоваться запустить библиотеку в отдельном «AppDomain», чтобы вы могли ее закрыть. – Enigmativity
Я согласен с @Enigmativity, за исключением того, что для полной изоляции вам понадобится отдельный * процесс *, а не только AppDomain. –