异步Folder.Bind上的ArgumentException

Jür*_*ann 2 c# exchangewebservices ews-managed-api exchange-server-2010

我们使用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;
    }
Run Code Online (Sandbox Code Playgroud)

我的真实场景是我使用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视图)

Jür*_*ann 5

我向微软发了一封电话,得到了这个答案......

我来自Messaging Developer Support团队,现在已经取得了此案例的所有权.我已经在论坛中对这个问题进行了描述,并根据示例代码,简单的答案是ExchangeService不保证是线程安全的,除非作为公共静态成员(参见http:/ /msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.exchangeservice(v=exchg.80).aspx).

您可以使用各种技术来避免此问题.您可以为每个线程使用ExchangeService,但如果您有很多线程同时运行,这可能是不可取的,因为您可能会遇到限制限制(每个服务实例可能会导致服务器上的新会话).您可以为文件夹对象实现缓存,这样,如果不同的线程请求相同的对象,则缓存对象可以在已经请求时返回它(这也会提高性能,因为它会减少对服务器的请求).

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

因此,我的解决方案是创建一个名为"SafeExecuter"的类,注意每个用户只能同时调用Exchange.还要注意不要超过限制政策.