mirror of
https://github.com/HolographicHat/Yae.git
synced 2025-12-06 14:42:52 +08:00
implement WhenFirstSuccessful method for improved task handling
This commit is contained in:
@@ -35,18 +35,21 @@ public static class Utils {
|
|||||||
//
|
//
|
||||||
if (_updateInfo?.CdnFiles.TryGetValue(path, out var cdnFile) == true) {
|
if (_updateInfo?.CdnFiles.TryGetValue(path, out var cdnFile) == true) {
|
||||||
try {
|
try {
|
||||||
var tasks = cdnFile.Urls.Select(url => GetFileFromCdn(url, cacheKey, cdnFile.Hash, cdnFile.Size));
|
var data = await cdnFile.Urls
|
||||||
var data = await Task.WhenAny(tasks).Unwrap();
|
.Select(url => GetFileFromCdn(url, cacheKey, cdnFile.Hash, cdnFile.Size))
|
||||||
|
.WhenFirstSuccessful()
|
||||||
|
.Unwrap();
|
||||||
transaction.Finish();
|
transaction.Finish();
|
||||||
return data;
|
return data;
|
||||||
} catch (Exception e) when (e is SocketException or TaskCanceledException or HttpRequestException or InvalidDataException) {}
|
} catch (Exception e) when (e is SocketException or TaskCanceledException or HttpRequestException or InvalidDataException) {}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
try {
|
try {
|
||||||
var data = await Task.WhenAny(
|
var data = await WhenFirstSuccessful([
|
||||||
GetFileReal($"https://rin.holohat.work/{path}", cacheKey),
|
GetFileReal($"https://rin.holohat.work/{path}", cacheKey),
|
||||||
|
GetFileReal($"https://ena-rin.holohat.work//{path}", cacheKey),
|
||||||
GetFileReal($"https://cn-cd-1259389942.file.myqcloud.com/{path}", cacheKey)
|
GetFileReal($"https://cn-cd-1259389942.file.myqcloud.com/{path}", cacheKey)
|
||||||
).Unwrap();
|
]).Unwrap();
|
||||||
transaction.Finish();
|
transaction.Finish();
|
||||||
return data;
|
return data;
|
||||||
} catch (Exception e) when (e is SocketException or TaskCanceledException or HttpRequestException) {
|
} catch (Exception e) when (e is SocketException or TaskCanceledException or HttpRequestException) {
|
||||||
@@ -327,4 +330,26 @@ public static class Utils {
|
|||||||
CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); // todo: use better way like auto set console font etc.
|
CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); // todo: use better way like auto set console font etc.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/76953892
|
||||||
|
private static async Task<Task<TResult>> WhenFirstSuccessful<TResult>(this IEnumerable<Task<TResult>> tasks) {
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
Task<TResult>? selectedTask = null;
|
||||||
|
var continuations = tasks
|
||||||
|
.TakeWhile(_ => !cts.IsCancellationRequested)
|
||||||
|
.Select(task => {
|
||||||
|
return task.ContinueWith(t => {
|
||||||
|
if (t.IsCompletedSuccessfully) {
|
||||||
|
if (Interlocked.CompareExchange(ref selectedTask, t, null) is null) {
|
||||||
|
cts.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, cts.Token, TaskContinuationOptions.DenyChildAttach | TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||||||
|
});
|
||||||
|
var whenAll = Task.WhenAll(continuations);
|
||||||
|
try {
|
||||||
|
await whenAll.ConfigureAwait(false);
|
||||||
|
} catch when (whenAll.IsCanceled) { /* ignore */ }
|
||||||
|
return selectedTask!;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user