1

私は多層アプリケーションに取り組んでおり、3つの方法で長時間実行プロセスを最適化する必要があります。

  1. EF更新の同時実行性の問題を回避します。
  2. 速度の向上。
  3. 進行状況をユーザーに通知します。

実際、クライアントコードは、すべての作業更新するエンティティの数の評価、更新するエンティティのクエリ、更新、最後にデータベースへの保存)を実行するメソッドを使用してWCFサービスを呼び出します。

プロセスは非常に長く、プロセスが完了すると最終結果を除いてユーザーに何も返されません。ユーザーは、何が起こっているのかわからなくても、最大10分間待機フォームの前にとどまることができます。

クエリされるエンティティの数と深さが非常に大きくなる可能性があり、OutOfMemoryExceptionsが発生することがあります。一度に100個のエンティティの更新を処理するようにサービスメソッドを変更する必要があったため、DbContextは頻繁に更新され、大きくなりすぎません。

私の実際の問題は、エンティティが更新されるたびにユーザーに通知できないことです。これは、サービスメソッドがプロセス全体を実行してから、結果をユーザーに返すためです。

デュプレックスサービスの実装について読みましたが、2つの異なるコールバックをユーザーに返す必要があるため(1つは更新するエンティティの数を返すコールバック、もう1つは各エンティティの更新結果のコールバック)、一般的なコールバックインターフェイスとそれは少し厄介になっています(まあ、私の好みに)。

評価するエンティティの数を返す1つのWCFサービスメソッドと、更新するすべてのエンティティに対してヒットする単純なエンティティ更新結果を返す別のWCFメソッドがある方がよいのではないでしょうか。私のDBContextは、単一のエンティティが更新されている間だけ存続するので、あまり大きくならないでしょう。これは良いことだと思います。ただし、そのプロセス中にWCFサービスに頻繁にアクセスすることを心配しています

あなたはどう思いますか?あなたは何を提案できますか?

4

2 に答える 2

0

クライアントにWCFホストを追加することを考えましたか?そうすれば、完全な双方向通信を利用できます。

クライアントはサーバーに接続し、サーバー接続の詳細をクライアントに返します。クライアントは
長時間実行操作を開始するように要求します
。サーバーは、作業の進行に応じてクライアントのWCFホストに複数の更新を送信します。
サーバーは作業完了をクライアントに送信します。

これにより、クライアントは他のことを自由に行えるようになり、サーバーからのメッセージを適切と思われるように消費します。メッセージが届いたときにステータス領域を更新するかもしれません。

サーバーにクライアントのリストを維持させ、それらすべてに更新を送信させることもできます。

--------編集---------
私がWCFホストと言うとき、私はServiceHostを意味 します。これは、App.configのXMLから、またはコードを介して直接作成できます。

var myUri = new Uri[0];
myUri[0] = new Uri("net.tcp://localhost:4000");
var someService = new SomeService(); //implements ISomeService interface
var host = new ServiceHost(someService, myUri);
var binding = new NetTcpBinding(); // need to configure this
host.AddServiceEndpoint(typeof(ISomeService), binding, "");
host.Open();

プロキシは、クライアントがサーバーに接続するために使用する用語です。初期の例では、私が出くわし、それ以来、私に固執していました。ここでも、両方の方法で作成できます。

var binding = new NetTcpBinding(); // need to configure this
var endpointAddress = new EndpointAddress("net.tcp://localhost:4000");
var factory = new ChannelFactory<ISomeService>(binding, endpointAddress);
var proxy = factory.CreateChannel();
proxy.DoSomeWork();

したがって、一般的なクライアント/サーバーアプリでは

CLIENT APP 1       SERVER APP         CLIENT APP 2
proxy------------->ServiceHost<-------proxy

私が提案しているのは、クライアントを「サーバー」にすることもできるということです。

CLIENT APP 1       SERVER APP         CLIENT APP 2
proxy------------->ServiceHostA<------proxy
ServiceHostB<------proxy1
                   proxy2------------>ServiceHostB

そうすれば、必要に応じて大きなタスクを小さなタスクに分割することもできます(メモリの問題について言及しました)が、物事の音からはまだ時間がかかる可能性があり、このようにして進捗状況の更新をクライアントに送り返すことができます。何が起こっているのかをみんなに知ってもらいたいのなら、すべてのクライアントでさえ。コールバックは必要ありませんが、必要に応じて使用できます。

于 2012-10-24T02:42:36.310 に答える
0
  1. EF 更新の同時実行の問題を回避します。

    この質問/回答を参照してください実行時間の長い Entity Framework トランザクション

  2. 速度の向上。

    いくつかの提案:

    • SQL Profiler を使用して、実行されている SQL クエリを確認し、linq クエリを最適化してみてください
    • または、クエリ自体を改善するか、ストアド プロシージャを呼び出してみてください。
    • 更新は並行して実行できますか? 異なるスレッド?異なるプロセッサ?
  3. ユーザーに進行状況を通知します。

    クライアントを変更して、非同期メソッド、または長時間実行される操作を非同期で開始するメソッドを呼び出すことをお勧めします。これにより、すぐに制御がクライアントに返されます。その後、進行状況に関するフィードバックを提供するのは、長期実行オペレーション次第です。

    バックグラウンド スレッドから進行状況を更新するには、この記事を参照してください


    私が提案する「アーキテクチャ」を更新すると、次のようになります。

              . サービス 。. .
    ________ . __________ ________ ____
   | | | | . | | WCF | | | EF | | | | |
   | | クライアント |---->| サービス |->| クラス |->| データベース |
   |________| . |_________| |_______| |____|
              .
              . .

WCF サービスは、クライアント要求を受け入れ、EF クラスで長時間実行される操作を開始することのみを担当します。クライアントは、WCF サービスに非同期要求を送信して、制御と応答性を維持する必要があります。EF クラスはデータベースの更新を担当し、一度にすべてまたはサブセットまたはレコードを更新することを選択できます。その後、EF クラスは、必要に応じて、進行状況を WCF サービスを介してクライアントに通知できます。

于 2012-10-23T19:54:25.167 に答える