我们使用 EWS 托管 API 将我们的 CRM 与 Exchange 服务器同步。只要我使用 EWS Mangage API 1.1,一切都很完美。现在我更新到 Api 2.0(Dll 版本:15.0.516.14),如果我从不同线程绑定(bind)到同一个文件夹并且不明白为什么,我会收到 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("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5e2a3b2d2a1e383131703d3133" rel="noreferrer noopener nofollow">[email protected]</a>");
return result;
}
我的真实场景是,我使用 pullsubscription 获取更改的项目并异步处理更改。在执行此操作时,我绑定(bind)到父文件夹以获取一些信息。
任何人都可以帮助我避免异常吗?
堆栈跟踪和异常信息:
System.ArgumentException:已添加具有相同键的项目。
at System.Collections.Generic.Dictionary2.Insert(TKey key, TValue value, Boolean add)
在 Microsoft.Exchange.WebServices.Data.ExchangeServiceBase.SaveHttpResponseHeaders(WebHeaderCollection header )
在 Microsoft.Exchange.WebServices.Data.SimpleServiceRequestBase.ReadResponse(IEwsHttpWebResponse 响应)
在 Microsoft.Exchange.WebServices.Data.ExchangeService.InternalFindFolders(IEnumerable
1parentFolderIds、SearchFilter searchFilter、FolderView View 、ServiceErrorHandling errorHandlingMode)
在 Microsoft.Exchange.WebServices.Data.ExchangeService.FindFolders(FolderId ParentFolderId,FolderView View )
最佳答案
我向 Microsoft 调用了支持电话并得到了这个答案...
我来自消息开发人员支持团队,现在已经接管了此案例。我已经按照您在论坛中描述的那样查看了该问题,并且根据那里的示例代码,简单的答案是 ExchangeService 不能保证线程安全,除非作为公共(public)静态成员(请参阅 http://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.exchangeservice(v=exchg.80).aspx )。
您可以使用多种技术来避免此问题。您可以为每个线程使用 ExchangeService,但如果您同时运行大量线程,则这可能是不可取的,因为您很可能会达到限制(每个服务实例可能会在服务器上产生一个新 session )。您可以为文件夹对象实现缓存,这样,如果不同的线程请求同一对象,则缓存对象可以在已经请求过的情况下返回该对象(这也会提高性能,因为它会减少对服务器的请求)。
需要注意的重要一点是,由于 EWS 是一个 Web 应用程序,因此您应该谨慎使用多线程,并尽量减少工作线程的数量。如果每个工作线程都生成对 Exchange 服务器的请求,那么与使用一个工作线程相比,您不太可能获得太多性能提升,因为您将等待 Exchange 的响应。
因此,我的解决方案是创建一个名为“SafeExecuter”的类,该类负责同时仅对每个用户的 Exchange 进行调用。它还会注意不超过限制策略。
关于c# - 异步文件夹上的 ArgumentException.Bind,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14871340/