Skip to content

Commit

Permalink
Added DisposeAsync, ResetAsync. Now Login() starts Reactor on current…
Browse files Browse the repository at this point in the history
… context, useful for UI access within OnUpdates/OnOther (LoginUserIfNeeded was already doing that)
  • Loading branch information
wiz0u committed Sep 6, 2024
1 parent 9315913 commit 9fe6a9d
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
22 changes: 15 additions & 7 deletions src/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

namespace WTelegram
{
public partial class Client : IDisposable
public partial class Client : IDisposable, IAsyncDisposable
{
/// <summary>This event will be called when unsollicited updates/messages are sent by Telegram servers</summary>
/// <remarks>Make your handler <see langword="async"/>, or return <see cref="Task.CompletedTask"/> or <see langword="null"/><br/>See <see href="https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ReactorError.cs?ts=4#L30">Examples/Program_ReactorError.cs</see> for how to use this<br/>or <see href="https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ListenUpdates.cs?ts=4#L21">Examples/Program_ListenUpdate.cs</see> using the UpdateManager class instead</remarks>
Expand Down Expand Up @@ -178,10 +178,12 @@ private static string AskConfig(string config)
public static Task<InputCheckPasswordSRP> 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)
Expand All @@ -197,19 +199,24 @@ public void Dispose()
/// <summary>Disconnect from Telegram <i>(shouldn't be needed in normal usage)</i></summary>
/// <param name="resetUser">Forget about logged-in user</param>
/// <param name="resetSessions">Disconnect secondary sessions with other DCs</param>
public void Reset(bool resetUser = true, bool resetSessions = true)
public void Reset(bool resetUser = true, bool resetSessions = true) => ResetAsync(resetUser, resetSessions).Wait();

/// <summary>Disconnect from Telegram <i>(shouldn't be needed in normal usage)</i></summary>
/// <param name="resetUser">Forget about logged-in user</param>
/// <param name="resetSessions">Disconnect secondary sessions with other DCs</param>
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;
Expand Down Expand Up @@ -350,7 +357,7 @@ private async Task Reactor(Stream stream, CancellationTokenSource cts)
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))
Expand Down Expand Up @@ -1047,6 +1054,7 @@ private async void RunLoginAsync(string phone)
};
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);
Expand Down
20 changes: 17 additions & 3 deletions src/Compat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
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);
Expand All @@ -19,7 +20,7 @@ static class Compat
#else // Compatibility shims for methods missing in netstandard2.0:
namespace WTelegram
{
static class Compat
static partial class Compat
{
internal static BigInteger BigEndianInteger(byte[] value)
{
Expand Down Expand Up @@ -104,4 +105,17 @@ public static T[] GetSubArray<T>(T[] array, Range range)
[EditorBrowsable(EditorBrowsableState.Never)]
internal class IsExternalInit { }
}
#endif
#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
}
}

0 comments on commit 9fe6a9d

Please sign in to comment.