我们使用EWS托管API将我们的CRM与Exchange-Server同步。只要我使用EWS Mangage API 1.1,一切都很完美。现在我更新到Api 2.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;
}
我的真实场景是我使用pullsubscription获取更改的项目并处理更改异步。在这样做时,我绑定到父文件夹以获取一些信息。
任何人都可以帮我避免异常吗?
Stacktrace和异常信息:
System.ArgumentException:已添加具有相同键的项目。
at 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(IEnumerable
1 parentFolderIds,SearchFilter searchFilter,FolderView视图,ServiceErrorHandling errorHandlingMode)
在Microsoft.Exchange.WebServices.Data.ExchangeService.FindFolders(FolderId parentFolderId,FolderView视图)
答案 0 :(得分:5)
我向微软发了一封电话,得到了这个答案......
我来自Messaging Developer Support团队,现已获得此案例的所有权。我已经在论坛中对此问题进行了描述,并根据示例代码,简单的答案是ExchangeService不保证是线程安全的,除非作为公共静态成员(参见{{3 }})。
您可以使用各种技术来避免此问题。您可以为每个线程使用ExchangeService,但如果您有很多线程同时运行,这可能是不可取的,因为您可能会遇到限制限制(每个服务实例可能会导致服务器上的新会话)。您可以为文件夹对象实现缓存,这样如果不同的线程请求相同的对象,如果已经请求了缓存对象,则缓存对象可以返回它(这也会提高性能,因为它会减少对服务器的请求)。
需要注意的一点是,由于EWS是一个Web应用程序,因此应谨慎使用多线程,并尽量减少工作线程的数量。如果每个工作线程都在向Exchange服务器生成请求,那么与使用一个工作线程相比,您不太可能在性能方面获得太多收益,因为您将等待来自Exchange的响应。
因此,我的解决方案是创建一个名为“SafeExecuter”的类,注意每个用户只能同时调用Exchange。还要注意不要超过限制政策。