既存の Silverlight 5 アプリケーションがあります。ユーザーがサードパーティのデータベース システム内のデータに対する一括更新を処理できるように、ページを追加しています。アプリケーションは現在、WCF RIA サービスを使用して、SOAP 経由でサード パーティ システムと通信します。更新の機能は、私が作成したワークフロー 4 アプリケーションに含まれており、SL アプリケーションのサーバー側でアセンブリとして参照されます。最後に、アプリケーションは現在、Windows 7 で実行されている IIS 7.5 のローカル インスタンスでホストされています。VS開発サーバーではなく、IISでもデバッグしています。
基本レベルでは、アプリケーションは次のように機能します。
- テキストファイルを選択
- 「開始」ボタンをクリック
- イベント ハンドラーは、バッチを追跡するユーザー定義の Type のインスタンスを作成します。
- イベント ハンドラは新しい
BackgroundWorker
インスタンスを作成し、DoWork
、ProgressChanged
、およびRunWorkerCompleted
イベントのハンドラを結び付けます - イベント ハンドラの呼び出し
RunWorkerAsync()
イベント ハンドラーの短縮コードを次に示しDoWork
ます。これは、作業の大部分がここで行われるためです。
private void BwOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs, BatchContainerControl batchProcess)
{
var worker = sender as BackgroundWorker;
// Iterate through each record of data file and call the 'UpdateAddress' function
// of the AddressDomainService which, in turn, executes the Workflow
foreach (var item in batchProcess.FileData)
{
// Check if operation has been cancelled
if (worker.CancellationPending)
{
doWorkEventArgs.Cancel = true;
break;
}
. . .
// Invoke THINKComm.CustomerAddressUpdate Workflow via AddressContext
var invokeOp = _addressDomainContext.UpdateAddress(activityData);
// 'activityData' is an instance of Dictionary<string, string>
invokeOp.Completed += (o, args) => InvokeOpOnCompleted(o, args, batchProcess);
}
}
ProgressChanged
とRunWorkerCompleted
イベントのハンドラー、およびインスタンス all のCompleted
イベントはInvokeOperation
、ほとんどの場合、UI の一部を更新します。そのコードの投稿が役立つと思われる場合は、喜んで投稿を更新します。
UI といえば、イベント ハンドラーによって更新される部分は 2 つのProgressBar
コントロールです。1 つはファイルから読み取られたときにレコードを追跡し、もう 1 つはサード パーティ データベースで更新が行われたときにレコードを追跡します。
実際の問題にたどり着く...
10、100、および 1,000 レコードのファイルを問題なく処理しました。次に、約 15,000 レコード (または 1,907KB のデータ) を含む完全なファイルを処理しようとしました。プロセスが開始され、ワークフローが実行されていることがデバッガーの出力で確認できます。約4分の1かそこらで、私はOutOfMemoryException
. スタック トレースは次のとおりです。
at System.ServiceModel.DomainServices.Client.WebDomainClient`1.BeginInvokeCore(InvokeArgs invokeArgs, AsyncCallback callback, Object userState)
at System.ServiceModel.DomainServices.Client.DomainClient.BeginInvoke(InvokeArgs invokeArgs, AsyncCallback callback, Object userState)
at System.ServiceModel.DomainServices.Client.DomainContext.InvokeOperation(String operationName, Type returnType, IDictionary`2 parameters, Boolean hasSideEffects, Action`1 callback, Object userState)
at THINKImportSystem.Web.Address.AddressDomainContext.UpdateAddress(Dictionary`2 activityData)
at THINKImportSystem.BatchProcessPage.BwOnDoWork(Object sender, DoWorkEventArgs doWorkEventArgs, BatchContainerControl batchProcess)
at THINKImportSystem.BatchProcessPage.<>c__DisplayClass10.<StartButtonClick>b__6(Object s, DoWorkEventArgs args)
at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.OnRun(Object argument)
次に、JIT デバッガーがポップアップし、次Unhandled Error in Silverlight Application Code:4004
のメッセージが表示されます。System.ServiceModel.DomainServices.Client.DomainOperationException: Invoke operation 'UpdateAddress' failed. Error HRESULT E_FAIL has been returned from a call to a COM component.
ときどき、JIT デバッガーを最初に入手することがあります。スレッドがまだ終了していることをデバッグ出力で確認し、約 10 秒または 20 秒後に、メモリ不足の例外で VS デバッガーがポップアップします。
私の最善の推測では、どこかのオブジェクト (おそらく DomainService に関連していますか?) が解放されていないため、メモリ使用量が増えています。私の理解では、IIS はアプリケーションが使用できるメモリの量に制限を設けていますが、ここでそうであるかどうかはわかりません。
ファイル内のレコードが処理されるたびに、その処理に関連するオブジェクトが解放されるため、全体的なメモリ使用量はかなり少なくなると考えていました。しかし、明らかに、すべてがどのように実行されているかを理解していません!
また、TPL を使用するのとは対照的に、違いが生じるかどうかも疑問に思っていましBackgroundWorker
たか?