2

EWS マネージ API を使用して、CRM を Exchange サーバーと同期します。EWS Mangage API 1.1 を使用している限り、すべてが完璧に機能しました。現在、Api 2.0 (Dll バージョン: 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;
    }

私の本当のシナリオは、プルサブスクリプションを使用して変更されたアイテムを取得し、変更を非同期に処理することです。これを行っている間、親フォルダーにバインドして情報を取得しています。

例外を回避するのを手伝ってくれる人はいますか?

スタックトレースと例外情報:

System.ArgumentException: 同じキーを持つアイテムが既に追加されています。

Microsoft.Exchange.WebServices.Data.ExchangeService.FindFolders (FolderId parentFolderId、FolderView ビュー)で 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)

4

1 に答える 1

5

マイクロソフトにサポートコールを行ったところ、この回答が得られました...

私は Messaging Developer Support チームの一員であり、このケースの所有権を取得しました。フォーラムで説明されているように問題を調べました。そこのサンプル コードに基づいて、簡単な答えは、ExchangeService が public static メンバーとして以外はスレッド セーフであることが保証されていないということです ( http:/を参照)。 /msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.exchangeservice(v=exchg.80).aspx )。

この問題を回避するために使用できるさまざまな手法があります。スレッドごとに ExchangeService を使用することもできますが、スロットリングの制限に達する可能性があるため (各サービス インスタンスによってサーバー上で新しいセッションが発生する可能性があるため)、一度に多数のスレッドを実行している場合はお勧めできません。フォルダー オブジェクトのキャッシュを実装して、別のスレッドが同じオブジェクトを要求した場合、既に要求されている場合はキャッシュ オブジェクトがそれを返すことができるようにすることができます (これにより、サーバーへの要求が減るため、パフォーマンスも向上します)。

注意すべき重要な点は、EWS は Web アプリケーションであるため、マルチスレッドを慎重に使用し、ワーカー スレッドの数を最小限に抑える必要があるということです。各ワーカー スレッドが Exchange サーバーへの要求を生成している場合、Exchange からの応答を待機することになるため、1 つのワーカー スレッドを使用する場合と比較して、パフォーマンス面で大きなメリットが得られる可能性はほとんどありません。

したがって、私の場合の解決策は、「SafeExecuter」というクラスを作成することでした。このクラスは、ユーザーごとの Exchange への呼び出しのみが同時に行われるように注意します。また、throttlingpolicy を超えないように注意します。

于 2013-03-22T07:49:41.193 に答える