Skip to content

Commit de028bb

Browse files
committed
Refactor WaitForInternetConnection async so it doesn't depend on Pings (issues with certain firewalls)
1 parent 414b839 commit de028bb

3 files changed

Lines changed: 53 additions & 29 deletions

File tree

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<ImplicitUsings>enable</ImplicitUsings>
44
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
5-
<WindowsSdkPackageVersion>10.0.26100.56</WindowsSdkPackageVersion>
5+
<WindowsSdkPackageVersion>10.0.26100.57</WindowsSdkPackageVersion>
66
<SdkVersion>8.0.405</SdkVersion>
77
<Authors>Martí Climent and the contributors</Authors>
88
<PublisherName>Martí Climent</PublisherName>

src/UniGetUI.Core.Classes/TaskRecycler.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,16 @@ namespace UniGetUI.Core.Classes;
1919
public static class TaskRecycler<ReturnT>
2020
{
2121
private static readonly ConcurrentDictionary<int, Task<ReturnT>> _tasks = new();
22+
private static readonly ConcurrentDictionary<int, Task> _tasks_VOID = new();
2223

2324
// ---------------------------------------------------------------------------------------------------------------
2425

26+
public static Task RunOrAttachAsync_VOID(Action method, int cacheTimeSecs = 0)
27+
{
28+
int hash = method.GetHashCode();
29+
return _runTaskAndWait_VOID(new Task(method), hash, cacheTimeSecs);
30+
}
31+
2532
/// Asynchronous entry point for 0 parameters
2633
public static Task<ReturnT> RunOrAttachAsync(Func<ReturnT> method, int cacheTimeSecs = 0)
2734
{
@@ -86,6 +93,37 @@ public static void RemoveFromCache(Func<ReturnT> method)
8693

8794
// ---------------------------------------------------------------------------------------------------------------
8895

96+
97+
/// <summary>
98+
/// Handles running the task if no such task was found on cache, and returning the cached task if it was found.
99+
/// </summary>
100+
private static async Task _runTaskAndWait_VOID(Task task, int hash, int cacheTimeSecsSecs)
101+
{
102+
if (_tasks_VOID.TryGetValue(hash, out Task? _task))
103+
{
104+
// Get the cached task, which is either running or finished
105+
task = _task;
106+
}
107+
else if (!_tasks_VOID.TryAdd(hash, task))
108+
{
109+
// Race condition, an equivalent task got added from another thread between the TryGetValue and TryAdd,
110+
// so we are going to restart the call to _runTaskAndWait in order for TryGetValue to return the new task again
111+
await _runTaskAndWait_VOID(task, hash, cacheTimeSecsSecs);
112+
return;
113+
}
114+
else
115+
{
116+
// Now that the new task is in the cache, run the task.
117+
task.Start();
118+
}
119+
120+
// Wait for the task to finish
121+
await task;
122+
123+
// Schedule the task for removal after the cache time expires
124+
_removeFromCache(hash, cacheTimeSecsSecs);
125+
}
126+
89127
/// <summary>
90128
/// Handles running the task if no such task was found on cache, and returning the cached task if it was found.
91129
/// </summary>

src/UniGetUI.Core.Tools/Tools.cs

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Security.Cryptography;
77
using System.Security.Principal;
88
using System.Text;
9+
using Windows.Networking.Connectivity;
910
using UniGetUI.Core.Classes;
1011
using UniGetUI.Core.Data;
1112
using UniGetUI.Core.Language;
@@ -639,42 +640,27 @@ public static ProcessStartInfo UpdateEnvironmentVariables(ProcessStartInfo info)
639640
/// Pings the update server and 3 well-known sites to check for internet availability
640641
/// </summary>
641642
public static async Task WaitForInternetConnection()
642-
=> await (await TaskRecycler<Task>.RunOrAttachAsync(_waitForInternetConnection));
643+
=> await TaskRecycler<int>.RunOrAttachAsync_VOID(_waitForInternetConnection);
643644

644-
public static async Task _waitForInternetConnection()
645+
public static void _waitForInternetConnection()
645646
{
646647
if (Settings.Get("DisableWaitForInternetConnection")) return;
647648

648-
Logger.Debug("Checking for internet connectivity. Pinging google.com, microsoft.com, couldflare.com and marticliment.com");
649-
string[] hosts = ["google.com", "microsoft.com", "cloudflare.com", "github.com"];
650-
while (true)
649+
Logger.Debug("Checking for internet connectivity...");
650+
bool internetLost = false;
651+
652+
var profile = NetworkInformation.GetInternetConnectionProfile();
653+
while (profile is null || profile.GetNetworkConnectivityLevel() is not NetworkConnectivityLevel.InternetAccess)
651654
{
652-
foreach (var host in hosts)
655+
Thread.Sleep(1000);
656+
profile = NetworkInformation.GetInternetConnectionProfile();
657+
if (!internetLost)
653658
{
654-
using (var pinger = new Ping())
655-
{
656-
try
657-
{
658-
PingReply reply = await pinger.SendPingAsync(host, 10);
659-
if (reply.Status is IPStatus.Success)
660-
{
661-
Logger.Debug(
662-
$"{host} responded successfully to ping, internet connection was validated.");
663-
return;
664-
}
665-
666-
Logger.Debug($"Could not ping {host}!");
667-
}
668-
catch (Exception ex)
669-
{
670-
Logger.Debug(
671-
$"Could not ping {host} with error {ex.Message}. Are you connected to the internet?");
672-
}
673-
}
659+
Logger.Warn("User is not connected to the internet, waiting for an internet connectio to be available...");
660+
internetLost = true;
674661
}
675-
676-
await Task.Delay(TimeSpan.FromSeconds(5));
677662
}
663+
Logger.Debug("Internet connectivity was established.");
678664
}
679665

680666
public static string TextProgressGenerator(int length, int progressPercent, string? extra)

0 commit comments

Comments
 (0)