如果其中一个线程失败,是否有任何方法可以停止其他并发线程的执行?我正在开发一个 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);
}
最佳答案
Instead of sending too many API requests in sequential fashion, I am creating threads, each thread consuming one API call.
这种方法几乎会破坏您服务器的任何可扩展性。您应该使用异步并发(多个操作),而不是并行并发(多线程)。您的 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#:如果一个线程失败,则终止其他线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38012732/