我们使用EWS托管API将我们的CRM与Exchange-Server同步。只要我使用了EWS Mangage API1.1,一切都运行得很完美。现在我更新到Api2.0 (Dll-version: 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;
}我的真实场景是,im使用pullsubscription获取更改的项目,并异步处理这些更改。在执行此操作时,我将绑定到父文件夹以获取一些信息。
有没有人能帮我避免这个异常?
堆栈跟踪和异常信息:
System.ArgumentException:已添加具有相同键的项。
在System.Collections.Generic.Dictionary2.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视图,SearchFilter searchFilter,FolderView视图,ServiceErrorHandling errorHandlingMode)在Microsoft.Exchange.WebServices.Data.ExchangeService.FindFolders(FolderId parentFolderId,FolderView视图)
发布于 2013-03-22 15:49:41
我给微软打了一个支持电话,得到的答案是...
我来自消息传递开发人员支持团队,现在已经接管了这个案例。正如您在论坛中描述的那样,我已经研究了这个问题,并且基于那里的示例代码,简单的答案是,除了作为公共静态成员(参见http://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.exchangeservice(v=exchg.80).aspx )之外,不能保证ExchangeService是线程安全的。
您可以使用各种技术来避免这个问题。您可以为每个线程使用一个ExchangeService,但是如果您有许多线程同时运行,那么这样做可能不可取,因为您可能会达到限制(每个服务实例可能会在服务器上产生一个新会话)。您可以为文件夹对象实现一个缓存,这样如果不同的线程请求相同的对象,缓存对象就可以在它已经被请求的情况下返回它(这也将提高性能,因为它将减少对服务器的请求)。
需要注意的重要一点是,由于EWS是一个web应用程序,您应该谨慎使用多线程,并最小化工作线程的数量。如果每个工作线程都在生成对Exchange服务器的请求,则与使用一个工作线程相比,您不太可能在性能方面获得很大提高,因为您将等待来自Exchange的响应。
因此,在我的案例中,解决方案是创建一个名为"SafeExecuter“的类,它注意同时只调用每个用户的Exchange。此外,它还会注意不超过throttlingpolicy。
https://stackoverflow.com/questions/14871340
复制相似问题