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
+ }
+}