使用 Office 365 的 EWS 中的超时和冻结

Timeouts and Freezing in EWS with Office 365

我有一项监视 2 个电子邮件收件箱的服务。为每个收件箱创建一个线程。新邮件在启动时被读取并标记为已读,然后 NewMail 事件处理程序处理之后的所有新邮件。

我们一直在使用 EWS 版本 14。我们在检索电子邮件时没有遇到任何问题。

我们将电子邮件移至 Office 365 后,问题开始了。

启动时,现有新消息的检索和处理仍然正常。

启动后,当 NewMail 事件处理程序被触发时,bind/load 方法超时,无论我们将 Timeout 属性 设置为什么。

我们尝试切换到最新的 EWS 版本 (15.0)。

对于新版本,启动处理仍然可以正常工作。

但是,尝试在 NewMail 事件处理程序中绑定一封电子邮件不会出错,但会使收件箱线程退出。

当两个收件箱中都有一封新电子邮件时,整个服务会在绑定线上冻结(我让它等待 40 分钟,然后不得不终止服务)。

我们尝试了以下两个 EWS 版本,但没有成功:

以下代码用于 NewEmail 事件处理程序和现有新邮件的启动处理。为什么相同的代码会在一个地方出现问题,而在另一个地方却没有?我该如何解决这个问题?

我也尝试过 EmailMessage.Bind 使用 NotificationEventArgs 对象,但我遇到了同样的问题。

我们尝试了 SyncLock 来绕过锁定 and/or 超时,但这没有帮助。 谢谢!

 Private Sub HaveMail(ByVal sender As Object, ByVal e As Microsoft.Exchange.WebServices.Data.NotificationEventArgs)
    Dim error_occured As Boolean = False
    Try
        Try
            SyncLock lock
                Logger.LogDebug("Just entered the Locked state of the HaveMail event")
                Dim ir As FindItemsResults(Of Item) = service.FindItems(WellKnownFolderName.Inbox, New SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, False), New ItemView(20))

                Do While ir.Items.Count > 0
                    For Each i As EmailMessage In ir
                        Try
                            Logger.LogDebug("About to load a newly received email message")
                            i.Load(PropertySet.FirstClassProperties)
                        Catch ex As Exception
                            Throw New Exception("Error while loading an email message: " & ex.Message)
                        End Try
                        Dim rm As New ReceivedMessage
                        rm.ReceivedDateTime = i.DateTimeReceived
                        rm.ToAddress = i.DisplayTo
                        rm.Subject = i.Subject
                        rm.Body = i.Body
                        rm.FromAddress = i.From.Address
                        Logger.LogDebug("Just loaded a newly received email message from " & rm.FromAddress)
                        Dim rme As New ReceivedMessageEvent
                        rme.msg = rm
                        RaiseEvent GotMail(Me, rme)
                        Logger.LogDebug("Just processed a newly received email message from " & rm.FromAddress)
                        i.IsRead = True
                        i.Update(ConflictResolutionMode.AlwaysOverwrite)
                    Next
                    ir = service.FindItems(WellKnownFolderName.Inbox, New SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, False), New ItemView(20))
                Loop

            End SyncLock

一般来说,在实际的事件处理程序中做任何事情都不是一个好习惯。因此 Update、FindItems 和 Bind 都会从您的处理程序中回调 EWS,这并不好。 ExchangeService 对象也不是线程安全的。在 O365 之前,您是如何摆脱困境的?除了幸运,我没有答案。

多亏了我在 MSN 上发帖的回答,我才得以解决问题。 我需要将 DefaultConnectionLimit 提高到 100。显然,它默认为 2,这还不够。