2

我们使用 EWS 托管 API 将我们的 CRM 与 Exchange 服务器同步。只要我使用 EWS Manage API 1.1,一切都很完美。现在我更新到 Api 2.0(Dll 版本:15.0.516.14),如果我从不同的线程绑定到同一个文件夹并且不明白为什么,我会收到 ArgumentException。

这是引发异常的示例代码:

private void TestAsyncFolderGet()
    {
        try
        {
            ExchangeService service = this.GetService();

            Parallel.For(0, 20, (i) =>
                {
                    Folder fo = Folder.Bind(service, WellKnownFolderName.Inbox);
               });

        }
        catch (Exception ex)
        {
            this.State = "Failed: " + ex.Message;
        }
    }

    private ExchangeService GetService()
    {
        ExchangeService result = new ExchangeService(ExchangeVersion.Exchange2010);

        result.AutodiscoverUrl("test@foo.com");

        return result;
    }

我的真实情况是我使用 pullsubscription 获取更改的项目并异步处理更改。在执行此操作时,我将绑定到父文件夹以获取一些信息。

谁能帮我避免异常?

Stacktrace 和异常信息:

System.ArgumentException:已添加具有相同键的项目。

在 System.Collections.Generic.Dictionary 2.Insert(TKey key, TValue value, Boolean add) at Microsoft.Exchange.WebServices.Data.ExchangeServiceBase.SaveHttpResponseHeaders(WebHeaderCollection headers) at Microsoft.Exchange.WebServices.Data.SimpleServiceRequestBase.ReadResponse(IEwsHttpWebResponse response) at Microsoft.Exchange.WebServices.Data.ExchangeService.InternalFindFolders(IEnumerable1 parentFolderIds,SearchFilter searchFilter,FolderView 视图,ServiceErrorHandling errorHandlingMode)在 Microsoft.Exchange.WebServices.Data.ExchangeService.FindFolders(FolderId parentFolderId,FolderView 视图)

4

1 回答 1

5

我给微软打了一个支持电话,得到了这个答案......

我来自消息传递开发人员支持团队,现在已经掌握了这个案例。我已经查看了您在论坛中描述的问题,并且根据那里的示例代码,简单的答案是 ExchangeService 不能保证是线程安全的,除非作为公共静态成员(请参阅http:/ /msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.exchangeservice(v=exchg.80).aspx )。

您可以使用多种技术来避免该问题。您可以为每个线程使用 ExchangeService,但如果您同时运行大量线程,则可能不建议这样做,因为您可能会达到限制限制(每个服务实例都可能导致服务器上的新会话)。您可以为文件夹对象实现缓存,这样如果不同的线程请求同一个对象,缓存对象可以在已经被请求的情况下返回它(这也将提高性能,因为它会减少对服务器的请求)。

需要注意的重要一点是,由于 EWS 是一个 Web 应用程序,因此您应该谨慎使用多线程,并尽量减少工作线程的数量。如果每个工作线程都在向 Exchange 服务器生成请求,那么与使用一个工作线程相比,您不太可能在性能方面获得太多收益,因为您将等待来自 Exchange 的响应。

因此,在我的案例中,解决方案是创建一个名为“SafeExecuter”的类,该类注意只对每个用户进行 Exchange 调用。还要注意不超过 throttlingpolicy。

于 2013-03-22T07:49:41.193 回答