首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >这两种对事件的订阅方式与在第二种情况下是否需要取消订阅之间的区别

这两种对事件的订阅方式与在第二种情况下是否需要取消订阅之间的区别
EN

Stack Overflow用户
提问于 2021-11-11 20:12:54
回答 1查看 299关注 0票数 0

我订阅了下面的事件,我想知道下面两个示例之间的区别是什么,我需要取消订阅吗?我使用的库是Binance.Net by JKorf。

代码语言:javascript
运行
复制
public event Action<Exception> Exception
{
    add => subscription.Exception += value;
    remove => subscription.Exception -= value;
}

示例1

代码语言:javascript
运行
复制
// Subscribe
subscription.Data.Exception += PortfolioService_Exception;

// Unsubscribe
subscription.Data.Exception -= PortfolioService_Exception;

private void PortfolioService_Exception(Exception ex)
{
    _logger.LogInformation($"Error: {ex.StackTrace}");
}

例2

如果我这样做,我需要取消订阅-=吗?

代码语言:javascript
运行
复制
subscription.Data.Exception += (ex) =>
{
    _logger.LogInformation($"Error: {ex.StackTrace}");
};

全码

片段

代码语言:javascript
运行
复制
private async Task<bool> InitAsync()
{
    var restClient = new BinanceClient(new BinanceClientOptions
    {
        ApiCredentials = new ApiCredentials(ApiKey, SecretKey),
        AutoTimestamp = true,
        AutoTimestampRecalculationInterval = TimeSpan.FromMinutes(30),
        TradeRulesBehaviour = TradeRulesBehaviour.AutoComply,
#if DEBUG
        LogLevel = LogLevel.Debug,
        LogWriters = new List<ILogger> { _logger } // TODO: FIX
#endif
    });

    var socketClient = new BinanceSocketClient(new BinanceSocketClientOptions
    {
        ApiCredentials = new ApiCredentials(ApiKey, SecretKey),
        AutoReconnect = true,
        ReconnectInterval = TimeSpan.FromSeconds(15),
#if DEBUG
        LogLevel = LogLevel.Debug,
        LogWriters = new List<ILogger> { _logger } // TODO: FIX
#endif
    });
    
    var listenKeyResult = await restClient.Spot.UserStream.StartUserStreamAsync();
    if (!listenKeyResult.Success)
    {
        return false;
    }

    var subscription = await socketClient.Spot.SubscribeToUserDataUpdatesAsync(listenKeyResult.Data,
        null,
        null,
        data =>
        {
            // TODO: Fix the warning
            _logger.LogInformation($"ASD {data.Data.Balances}");
        },
        data =>
        {
            // TODO: Fix the warning
            _logger.LogInformation($"BALANCE DELTA {data.Data.BalanceDelta}");
        });

    if (!subscription.Success)
    {
        return false;
    }

    // Auto unsubscribe?
    subscription.Data.Exception += (ex) =>
    {
        _logger.LogInformation($"Error: {ex.StackTrace}");
    };

    // Subscribe
    subscription.Data.Exception += PortfolioService_Exception;

    // Unsubscribe
    subscription.Data.Exception -= PortfolioService_Exception;

    // TODO: Put a CancellationToken logic and `StopUserStreamAsync`. and subscription.Error -=
    var keepAliveTask = Task.Run(async () =>
    {
        while (true)
        {
            // Listen key is kept alive for 60 minutes.
            await restClient.Spot.UserStream.KeepAliveUserStreamAsync(listenKeyResult.Data);
            await Task.Delay(TimeSpan.FromMinutes(50));
        }
    });
    
    return true;
}

private void PortfolioService_Exception(Exception ex)
{
    _logger.LogInformation($"Error: {ex.StackTrace}");
}

图书馆

代码语言:javascript
运行
复制
using CryptoExchange.Net.Objects;
using System;
using System.Threading.Tasks;

namespace CryptoExchange.Net.Sockets
{
    /// <summary>
    /// Subscription to a data stream
    /// </summary>
    public class UpdateSubscription
    {
        private readonly SocketConnection connection;
        private readonly SocketSubscription subscription;

        /// <summary>
        /// Event when the connection is lost. The socket will automatically reconnect when possible.
        /// </summary>
        public event Action ConnectionLost
        {
            add => connection.ConnectionLost += value;
            remove => connection.ConnectionLost -= value;
        }

        /// <summary>
        /// Event when the connection is closed. This event happens when reconnecting/resubscribing has failed too often based on the <see cref="SocketClientOptions.MaxReconnectTries"/> and <see cref="SocketClientOptions.MaxResubscribeTries"/> options,
        /// or <see cref="SocketClientOptions.AutoReconnect"/> is false
        /// </summary>
        public event Action ConnectionClosed
        {
            add => connection.ConnectionClosed += value;
            remove => connection.ConnectionClosed -= value;
        }

        /// <summary>
        /// Event when the connection is restored. Timespan parameter indicates the time the socket has been offline for before reconnecting. 
        /// Note that when the executing code is suspended and resumed at a later period (for example laptop going to sleep) the disconnect time will be incorrect as the diconnect
        /// will only be detected after resuming. This will lead to an incorrect disconnected timespan.
        /// </summary>
        public event Action<TimeSpan> ConnectionRestored
        {
            add => connection.ConnectionRestored += value;
            remove => connection.ConnectionRestored -= value;
        }

        /// <summary>
        /// Event when the connection to the server is paused based on a server indication. No operations can be performed while paused
        /// </summary>
        public event Action ActivityPaused
        {
            add => connection.ActivityPaused += value;
            remove => connection.ActivityPaused -= value;
        }

        /// <summary>
        /// Event when the connection to the server is unpaused after being paused
        /// </summary>
        public event Action ActivityUnpaused
        {
            add => connection.ActivityUnpaused += value;
            remove => connection.ActivityUnpaused -= value;
        }

        /// <summary>
        /// Event when an exception happens during the handling of the data
        /// </summary>
        public event Action<Exception> Exception
        {
            add => subscription.Exception += value;
            remove => subscription.Exception -= value;
        }

        /// <summary>
        /// The id of the socket
        /// </summary>
        public int SocketId => connection.Socket.Id;

        /// <summary>
        /// The id of the subscription
        /// </summary>
        public int Id => subscription.Id;

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="connection">The socket connection the subscription is on</param>
        /// <param name="subscription">The subscription</param>
        public UpdateSubscription(SocketConnection connection, SocketSubscription subscription)
        {
            this.connection = connection;
            this.subscription = subscription;
        }
        
        /// <summary>
        /// Close the subscription
        /// </summary>
        /// <returns></returns>
        public Task CloseAsync()
        {
            return connection.CloseAsync(subscription);
        }

        /// <summary>
        /// Close the socket to cause a reconnect
        /// </summary>
        /// <returns></returns>
        internal Task ReconnectAsync()
        {
            return connection.Socket.CloseAsync();
        }

        /// <summary>
        /// Unsubscribe a subscription
        /// </summary>
        /// <returns></returns>
        internal async Task UnsubscribeAsync()
        {
            await connection.UnsubscribeAsync(subscription).ConfigureAwait(false);
        }

        /// <summary>
        /// Resubscribe this subscription
        /// </summary>
        /// <returns></returns>
        internal async Task<CallResult<bool>> ResubscribeAsync()
        {
            return await connection.ResubscribeAsync(subscription).ConfigureAwait(false);
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-11 22:12:58

示例1和示例2做的事情完全一样。唯一的区别是,在示例1中,您的处理程序有一个名称,而在示例2中,它没有名称(即匿名)。因为它没有名称,所以很难向-=注销处理程序,因为您似乎已经知道了这一点。

如果希望能够使用lambda,但也希望能够取消订阅,则可以首先将lambda分配给变量。

代码语言:javascript
运行
复制
Action<Exception> tmp = ex => _logger.LogInformation($"Error: {ex.StackTrace}");
subscription.Data.Exception += tmp;
subscription.Data.Exception -= tmp; //Unsubscribe
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69934367

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档