异步Folder.Bind上的ArgumentException

时间:2013-02-14 09:16:33

标签: c# exchangewebservices exchange-server-2010 ews-managed-api

我们使用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视图)

1 个答案:

答案 0 :(得分:5)

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

我来自Messaging Developer Support团队,现已获得此案例的所有权。我已经在论坛中对此问题进行了描述,并根据示例代码,简单的答案是ExchangeService不保证是线程安全的,除非作为公共静态成员(参见{{3 }})。

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

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

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