【问题标题】:Increasing the Lifetime element for EWS Streaming Subscription Connection增加 EWS 流订阅连接的 Lifetime 元素
【发布时间】:2011-09-16 15:39:01
【问题描述】:

使用 Microsoft 的 EWS,我们能够收听邮箱并在收到新电子邮件时采取措施。但是,我不知道如何避免连接超时。

根据 Microsoft,这是 StreamingSubscriptionConnection 的构造函数:

public StreamingSubscriptionConnection (
    ExchangeService service,
    int lifetime
)

在我的应用程序中,我将其编码如下:

service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
StreamingSubscriptionConnection conn = new StreamingSubscriptionConnection(service, 30);

换句话说,我将超时(生命周期)设置为 30 分钟,因为这是我能够设置的最高值。我怎样才能增加这个?或者,即使在收到的电子邮件之间间隔约 45 分钟,我如何才能欺骗此订阅以使其保持活跃?

【问题讨论】:

    标签: c# exchangewebservices


    【解决方案1】:

    30 分钟是硬性限制。您不能将其更改为更高的值。

    要解决此问题,请将处理程序连接到连接实例的 OnDisconnect 事件的 OnDisconnected 处理程序。从那里重新启动订阅(只需从该处理程序调用 connection.Open())。

    【讨论】:

    • 但是当它是一个合法的断开连接时呢?例如,有人停止了服务……我需要区分这两种情况。
    • 啊,我明白了。 “停止”被认为与断开连接不同。我要买它。谢谢
    • 让我测试一下,赏金将归你所有,@Henning Krause。
    • 如果新邮件刚好在断开通知和重新连接呼叫之间到达,会发生什么情况?我会错过那封邮件的通知吗?谢谢
    • 重新建立连接后,您可以手动执行 SyncFolderItems 请求以获取在该时间范围内发生的任何错过的事件。
    【解决方案2】:

    如果人们有兴趣,这里是添加的一点点逻辑。

    我将此添加到我的 Start 方法中:

    conn.OnDisconnect += 
        new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnDisconnect);
    

    然后我添加了 OnDisconnect 方法:

    private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
    {
        Start();
    }
    

    最终,这仍然需要改进,因为这只是超时并每半小时重新连接一次,无论收到的电子邮件活动如何。我宁愿在每次收到新消息时重置计数器。然后,它每天只会超时几次,而不是 48 次!尽管如此,这仍然是为了让我的电子邮件收听程序保持在线。

    【讨论】:

    • 你的 OnStart 方法是否不需要 string[] args 作为参数
    • 您没有显示您的 Start() 方法的内容,但是您正在做的事情让我感觉不好。我担心您每天都在创建 48 个 StreamingSubscriptionConnection 对象,并且它们不能被垃圾收集,因为它们有一个链接到它们的事件处理程序方法。所以你可能有内存泄漏。一个非常小的,在更大的计划中,但仍然......
    【解决方案3】:

    如果其他人有兴趣,我就是这样做的。

    我想保持连接打开,所以我在 OnDisconnect 处理程序中重置它。

    但是,在重置它之前,我使用反射检查了连接对象上的私有“订阅”字典。

    这允许我在代码中的其他位置取消订阅我的连接 (OnNotificationEvent),当所有订阅都被取消订阅后,我就可以关闭连接。

    这是我的代码:

     void connection_OnDisconnect(object sender, SubscriptionErrorEventArgs args)
        {
            var c = (Dictionary<string, StreamingSubscription>)typeof(StreamingSubscriptionConnection).GetField("subscriptions",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(sender);
    
            if (c.Count > 0)
            {
                // reopen the connection
                ((StreamingSubscriptionConnection)sender).Open();
    
                using (var db = new Metrics_DatabaseEntities())
                {
                    PushNotificationTest pt = new PushNotificationTest();
                    pt.RetObj = "Connection reset";
    
                    db.PushNotificationTests.Add(pt);
    
                    db.SaveChanges();
    
                }
            }
            else
            {
                using (var db = new Metrics_DatabaseEntities())
                {
                    PushNotificationTest pt = new PushNotificationTest();
                    pt.RetObj = "Connection closed!";
    
                    db.PushNotificationTests.Add(pt);
    
                    db.SaveChanges();
    
                }
            }
        }
    

    请忽略这种糟糕的写法,这只是我的第一个版本,因为我打算很快把它写得更干净。我只是想与可能感兴趣的人分享我的方法。

    【讨论】:

    • 可以直接使用StreamingSubscriptionConnection c = (StreamingSubscriptionConnection)sender;
    猜你喜欢
    • 2012-04-14
    • 1970-01-01
    • 2020-09-07
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    • 1970-01-01
    相关资源
    最近更新 更多