From 9fe6a9d74f24e0cae34ad8c43384f38801cee710 Mon Sep 17 00:00:00 2001 From: Wizou <11647984+wiz0u@users.noreply.github.com> Date: Fri, 6 Sep 2024 18:22:05 +0200 Subject: [PATCH] Added DisposeAsync, ResetAsync. Now Login() starts Reactor on current context, useful for UI access within OnUpdates/OnOther (LoginUserIfNeeded was already doing that) --- src/Client.cs | 22 +++++++++++++++------- src/Compat.cs | 20 +++++++++++++++++--- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/Client.cs b/src/Client.cs index 3a85c60..d470309 100644 --- a/src/Client.cs +++ b/src/Client.cs @@ -20,7 +20,7 @@ using static WTelegram.Encryption; namespace WTelegram { - public partial class Client : IDisposable + public partial class Client : IDisposable, IAsyncDisposable { /// This event will be called when unsollicited updates/messages are sent by Telegram servers /// Make your handler , or return or
See Examples/Program_ReactorError.cs for how to use this
or Examples/Program_ListenUpdate.cs using the UpdateManager class instead
@@ -178,10 +178,12 @@ namespace WTelegram public static Task InputCheckPassword(Account_Password accountPassword, string password) => Check2FA(accountPassword, () => Task.FromResult(password)); - public void Dispose() + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA1816")] + public void Dispose() => DisposeAsync().AsTask().Wait(); + public async ValueTask DisposeAsync() { Helpers.Log(2, $"{_dcSession.DcID}>Disposing the client"); - Reset(false, IsMainDC); + await ResetAsync(false, IsMainDC).ConfigureAwait(false); var ex = new ObjectDisposedException("WTelegram.Client was disposed"); lock (_pendingRpcs) // abort all pending requests foreach (var rpc in _pendingRpcs.Values) @@ -197,19 +199,24 @@ namespace WTelegram /// Disconnect from Telegram (shouldn't be needed in normal usage) /// Forget about logged-in user /// Disconnect secondary sessions with other DCs - public void Reset(bool resetUser = true, bool resetSessions = true) + public void Reset(bool resetUser = true, bool resetSessions = true) => ResetAsync(resetUser, resetSessions).Wait(); + + /// Disconnect from Telegram (shouldn't be needed in normal usage) + /// Forget about logged-in user + /// Disconnect secondary sessions with other DCs + public async Task ResetAsync(bool resetUser = true, bool resetSessions = true) { try { if (CheckMsgsToAck() is MsgsAck msgsAck) - SendAsync(msgsAck, false).Wait(1000); + await SendAsync(msgsAck, false).WaitAsync(1000).ConfigureAwait(false); } catch { } _cts?.Cancel(); _sendSemaphore = new(0); // initially taken, first released during DoConnectAsync try { - _reactorTask?.Wait(1000); + await _reactorTask.WaitAsync(1000).ConfigureAwait(false); } catch { } _reactorTask = resetSessions ? null : Task.CompletedTask; @@ -350,7 +357,7 @@ namespace WTelegram try { lock (_msgsToAck) _msgsToAck.Clear(); - Reset(false, false); + await ResetAsync(false, false); _reactorReconnects = (_reactorReconnects + 1) % MaxAutoReconnects; if (disconnectedAltDC && _pendingRpcs.Count <= 1) if (_pendingRpcs.Values.FirstOrDefault() is not Rpc rpc || rpc.type == typeof(Pong)) @@ -1047,6 +1054,7 @@ namespace WTelegram }; try { + await ConnectAsync(); // start reactor on the current (UI?) context // Login logic is executed on TaskScheduler while request TCS are still received on current SynchronizationContext await Task.Run(() => LoginUserIfNeeded()); _loginCfg.request.SetResult(null); diff --git a/src/Compat.cs b/src/Compat.cs index 53d54b4..4e9f9dc 100644 --- a/src/Compat.cs +++ b/src/Compat.cs @@ -6,11 +6,12 @@ using System.Linq; using System.Net; using System.Numerics; using System.Security.Cryptography; +using System.Threading.Tasks; #if NETCOREAPP2_1_OR_GREATER namespace WTelegram { - static class Compat + static partial class Compat { internal static BigInteger BigEndianInteger(byte[] value) => new(value, true, true); internal static IPEndPoint IPEndPoint_Parse(string addr) => IPEndPoint.Parse(addr); @@ -19,7 +20,7 @@ namespace WTelegram #else // Compatibility shims for methods missing in netstandard2.0: namespace WTelegram { - static class Compat + static partial class Compat { internal static BigInteger BigEndianInteger(byte[] value) { @@ -104,4 +105,17 @@ namespace System.Runtime.CompilerServices [EditorBrowsable(EditorBrowsableState.Never)] internal class IsExternalInit { } } -#endif \ No newline at end of file +#endif + +namespace WTelegram +{ + static partial class Compat + { + internal static Task WaitAsync(this Task source, int timeout) +#if NET8_0_OR_GREATER + => source?.WaitAsync(TimeSpan.FromMilliseconds(timeout)) ?? Task.CompletedTask; +#else + => source == null ? Task.CompletedTask : Task.WhenAny(source, Task.Delay(timeout)); +#endif + } +}