[英]Use CancelAfter on CancellationTokenSource with loop
我想創建一個實現超時的 class 助手。 因為任務一旦啟動就無法停止,我使用循環。 我想在不通過 GetAsync 的 CancellationToken 的情況下使用此模式。 我的問題是:這段代碼是你可以使用的最好的,還是循環會導致性能問題? 要了解示例:如果您更改https://reqres.in/api/users?delay=3 (延遲=4),您沒有超時。 如果沒有提出 CancelAfter 的另一個重要問題,為什么我的代碼仍然可以運行(請參閱 output )?
using System;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace RetryDemo {
class Program {
static void Main(string[] args) {
Example();
Console.ReadLine();
}
private static void Example() {
Stopwatch Stopwatch = Stopwatch.StartNew();
try {
AppDomain.CurrentDomain.UnhandledException += (sender, e) => { Console.WriteLine(((AggregateException)e.ExceptionObject).InnerExceptions.Single().Message); };
var source = new CancellationTokenSource();
var token = source.Token;
var task = Task.Run(async () => {
try {
using (token.Register(() => {
Console.WriteLine($"Timeout elapsed {Stopwatch.Elapsed}");
})) {
Task<HttpResponseMessage> message = GetPage("https://reqres.in/api/users?delay=4");
while (true) {
if (!token.IsCancellationRequested) {
if (message.IsCompleted) {
HttpResponseMessage messageSync = await message;
Console.WriteLine(await messageSync.Content.ReadAsStringAsync());
}
} else {
break;
}
Thread.Sleep(200);
Console.Write(".");
}
}
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
});
source.CancelAfter(3500);
} catch (Exception ex) {
Console.Write(ex.Message);
}
}
public static async Task<HttpResponseMessage> GetPage(string url) {
Console.WriteLine($"Calling page{url}");
HttpClient httpclient = new HttpClient();
return await httpclient.GetAsync(url);//.ConfigureAwait(false);
}
}
}
我想在不通過 GetAsync 的 CancellationToken 的情況下使用此模式。
請記住,取消是合作的,所以這最終只會取消等待而不是操作本身。
它是您可以使用的最好的還是循環會導致性能問題?
一個完全正確的解決方案相當棘手,因為很容易忘記在正確的時間處理所有東西。 我建議使用我的AsyncEx library中的TaskExtensions.WaitAsync(CancellationToken)
。 它不使用輪詢; 相反,它使用Register
在超時時立即取消等待。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.