サードパーティライブラリを使用して何千もの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);
}
}
最初はタスクを強制終了しないでください。いくつかの協調的なメカニズムを使用して操作を中断し、それが担当するセマフォを解放することができます。残念ながら、あなたの質問には、あなたのタスクの実装そのものを理解するために必要なすべての詳細が欠けていますが、一般的にはネットワークI/O(HTTPリクエストなど)を扱うときには、アクティブなスレッドを持つべきではありません。実行している操作のための.NET非同期API –
「どうすれば...殺すべき?」 - あなたはすべきではありません - スレッドを殺すことは悪い悪いです。サードパーティのライブラリがクラッシュしている場合は、別の 'AppDomain'でライブラリを実行して、きれいに閉じることができます。 – Enigmativity
完全分離のためには、AppDomainだけでなく、別の*プロセス*が必要である点を除いて、@Enigmativityに同意します。 –