使用 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,这还不够。
我有一项监视 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,这还不够。