如果其中一个线程发生故障,是否有任何方法可以停止其他并发线程的执行?我正在一个ASP.NET MVC网站上工作,该网站将大量使用API调用。我不是以顺序的方式发送太多的API请求,而是创建线程,每个线程消耗一个API调用。如果任何线程失败,我想杀死其他线程。我怎样才能做到这一点?我使用了Task.WaitAll
,但即使一个线程失败,它也允许所有其他线程执行。请帮忙。
更新:
为了模拟实时场景,我创建了一个控制台应用程序。请引用下面的代码。我想使第五个线程失败。在第五个线程失败后,我希望所有其他正在运行的线程停止。
public class Program
{
static int[] delays = { 3, 2, 10, 4, 5, 6, 7, 8, 9, 1 };
static int[] ids = new int[10];
static Task[] tasks = null;
static CancellationTokenSource tokenSource = new CancellationTokenSource();
static IList<int> threadsExecuted = new List<int>();
static void Main(string[] args)
{
ids = Enumerable.Range(1, 10).ToArray();
try
{
tasks = ids.Select(id => MyTaks(id)).ToArray();
Task.WaitAll(tasks);
}
catch (Exception exception)
{
Console.WriteLine("Exception in Main::\nMessage: " + exception.Message +
"StackTrace: " + exception.StackTrace +
"InnerException: " + exception.InnerException);
}
Console.WriteLine("\n\nThreads executed: " + string.Join(", ", threadsExecuted.OrderBy(id => id).ToArray()));
Console.WriteLine("\n\n\nExit..");
Console.Read();
}
private static async Task MyTaks(int id)
{
var delay = delays[id - 1] * 1000;
Console.WriteLine("Thread id #" + id + " started with delay " + delay + " seconds.");
CancellationToken cToken = tokenSource.Token;
Task task = new Task(() =>
{
Thread.Sleep(delay);
if (id == 5) //Fail
{
Console.WriteLine("Cancelling..");
throw new Exception("Thread id #" + id + " failed.");
}
}, cToken);
task.Start();
await task;
Console.WriteLine("Thread id #" + id + " executed.");
threadsExecuted.Add(id);
}
}
最佳答案
这种方法几乎会破坏服务器的任何可伸缩性。您应该使用异步并发(多个操作),而不是并行并发(多个线程)。您的API代码将使用HttpClient.GetAsync
并传递CancellationToken
。
因此,您的测试代码如下所示:
static void Main(string[] args)
{
ids = Enumerable.Range(1, 10).ToArray();
try
{
tasks = ids.Select(id => MyTaks(id)).ToArray();
Task.WaitAll(tasks);
}
catch (Exception exception)
{
Console.WriteLine("Exception in Main::\nMessage: " + exception.Message +
"StackTrace: " + exception.StackTrace +
"InnerException: " + exception.InnerException);
}
lock (threadsExecuted)
Console.WriteLine("\n\nThreads executed: " + string.Join(", ", threadsExecuted.OrderBy(id => id).ToArray()));
Console.WriteLine("\n\n\nExit..");
Console.Read();
}
private static async Task MyTaks(int id)
{
var delay = delays[id - 1] * 1000;
Console.WriteLine("Task id #" + id + " started with delay " + delay + " seconds.");
CancellationToken cToken = tokenSource.Token;
// Production code would use `await httpClient.GetAsync(url, token)` here.
await Task.Delay(delay, cToken);
if (id == 5) //Fail
{
Console.WriteLine("Cancelling..");
tokenSource.Cancel();
throw new Exception("Thread id #" + id + " failed.");
}
Console.WriteLine("Thread id #" + id + " executed.");
lock (threadsExecuted)
threadsExecuted.Add(id);
}
关于c# - C#:如果一个线程失败,则终止其他线程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38012732/