在一定时间后取消 Task.WhenAll
Posted
技术标签:
【中文标题】在一定时间后取消 Task.WhenAll【英文标题】:Cancelling Task.WhenAll after a certain amount of time 【发布时间】:2021-08-05 07:06:42 【问题描述】:我有一个异步操作,它将航空公司列表作为参数并返回一些数据,并且我有一个航空公司列表,我想为其获取数据。
但是,如果在预定义的时间后我无法获得所有这些航空公司的数据,我想停止等待并将其他内容返回给用户。
public async Task Run()
var watch = System.Diagnostics.Stopwatch.StartNew();
await RunAirline();
watch.Stop();
Console.WriteLine($"Total Execution Time: watch.ElapsedMilliseconds + Environment.NewLine");
//return $"Total Execution Time: watch.ElapsedMilliseconds + Environment.NewLine";
//Console.ReadLine();
private static async Task RunAirline()
try
List<string> AirlineList = GetAirLineCodes();
List<Task<WebsiteDataModel.WebsiteDataModel>> taskList = new List<Task<WebsiteDataModel.WebsiteDataModel>>();
foreach (string AirlineCode in AirlineList)
taskList.Add(Task.Run(() => CallindividualAirline(AirlineCode)));
var result = await Task.WhenAll(taskList);
foreach (WebsiteDataModel.WebsiteDataModel model in result)
Display(model);
catch (Exception Ex)
Console.WriteLine(Ex.Message.ToString());
private static List<string> GetAirLineCodes()
return new List<string>()
"A",
"B",
"C"
;
private static void Display(WebsiteDataModel.WebsiteDataModel result)
Console.WriteLine($"Website Content as result.DataContent , Website Name as : result.WebsiteName Status as : result.Status , Content length as : result.WebsiteData.Length ----- Error as : result.error.FaultException.ToString()." + Environment.NewLine);
private static WebsiteDataModel.WebsiteDataModel CallindividualAirline(string AirlineCode)
WebsiteDataModel.WebsiteDataModel LobjWebsiteDataModel = new WebsiteDataModel.WebsiteDataModel();
WebsiteDataModel.ErrorData LobjErrorData = new WebsiteDataModel.ErrorData();
try
switch (AirlineCode)
// calling Airline API...........
case "A":
ClsAirOne LobjAirOne = new ClsAirOne();
LobjWebsiteDataModel = LobjAirOne.GetAirDataData("https://book.xxxxx.com");
return LobjWebsiteDataModel;
case "B":
ClsAirTwo LobjAirTwo = new ClsAirTwo();
LobjWebsiteDataModel = LobjAirTwo.GetAirData("https://book.xxxxx.in");
return LobjWebsiteDataModel;
case "C":
ClsAirThree LobjAirThree = new ClsAirThree();
LobjWebsiteDataModel = LobjAirThree.GetAirData("https://xxxxx.in/");
return LobjWebsiteDataModel;
default:
return LobjWebsiteDataModel;
catch (Exception Ex)
LobjWebsiteDataModel.Status = "0";
LobjWebsiteDataModel.WebsiteData = "";
LobjErrorData.FaultException = "ERR-01" + Ex.Message.ToString();
LobjWebsiteDataModel.error = LobjErrorData;
return LobjWebsiteDataModel;
【问题讨论】:
有帮助吗? ***.com/questions/9846615/…CancellationTokenSource
@feihoa..........这两个 sn-ps 的组合实现了我的输出........await 任务。 WhenAny(Task.WhenAll(tasks), Task.Delay(timeout));var completedResults = tasks .Where(t => t.Status == TaskStatus.RanToCompletion) .Select(t => t.Result) .ToList() ;
var 结果 = await Task.WhenAny(Task.WhenAll(taskList), Task.Delay(TimeSpan.FromSeconds(Convert.ToDouble(ConfigurationManager.AppSettings["TimeOutInSeconds"]))));这个sn-p是否取消所有在特定时间内没有完成的任务
【参考方案1】:
执行此操作的最佳方法是取消传递给Task.WhenAll
的每个操作。您可以创建一个带有超时的取消令牌源,然后将其 CancellationToken
传递给实际执行 I/O 的方法。
例如:
public async Task Run()
...
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
await RunAirline(cts.Token);
...
private static async Task RunAirline(CancellationToken cancellationToken)
...
foreach (string AirlineCode in AirlineList)
taskList.Add(Task.Run(() => CallindividualAirline(AirlineCode, cancellationToken)));
...
private static WebsiteDataModel.WebsiteDataModel CallindividualAirline(string AirlineCode, CancellationToken cancellationToken)
...
ClsAirOne LobjAirOne = new ClsAirOne();
LobjWebsiteDataModel = LobjAirOne.GetAirDataData("https://book.xxxxx.com", cancellationToken);
...
ClsAirTwo LobjAirTwo = new ClsAirTwo();
LobjWebsiteDataModel = LobjAirTwo.GetAirData("https://book.xxxxx.in", cancellationToken);
...
【讨论】:
嗨斯蒂芬,我做了同样的事情。但它不会在 10 秒后停止。 @VIGNESHWARAN:您需要将CancellationToken
一直传递给调用 API 的任何对象。以上是关于在一定时间后取消 Task.WhenAll的主要内容,如果未能解决你的问题,请参考以下文章
Task CancellationTokenSource和Task.WhenAll的应用
Task.WhenAll(taskList).Wait() 是不是与 Task.WaitAll(taskList) 相同?