我有一个现有的 Silverlight 5 应用程序。我正在向其中添加一个页面,以允许用户处理对第三方数据库系统中数据的大量更新。该应用程序当前使用 WCF RIA 服务通过 SOAP 与第 3 方系统进行通信。更新的功能包含在我创建的 Workflow 4 应用程序中,并作为 SL 应用程序服务器端的程序集引用。最后,该应用程序现在托管在我在 Windows 7 上运行的本地 IIS 7.5 实例中;我也在用 IIS 调试,而不是 VS 开发服务器。
在基础层面,应用程序的功能如下:
- 选择文本文件
- 点击“开始”按钮
- 事件处理程序创建一个用户定义类型的实例,用于跟踪批次
- 事件处理程序创建一个新
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
,以及所有实例的Completed
事件,InvokeOperation
在大多数情况下,都会更新 UI 的一部分。如果您认为发布任何代码会有所帮助,我很乐意更新帖子。
说到 UI,事件处理程序更新的部分是两个ProgressBar
控件 - 一个在从文件中读取记录时跟踪记录,第二个在第 3 方数据库上发生更新时跟踪记录。
进入实际问题...
我已经毫无问题地处理了 10、100 和 1,000 条记录的文件。然后,我尝试处理包含约 15,000 条记录(或 1,907KB 数据)的完整文件。该过程开始,我可以在调试器输出中看到正在执行工作流。大约进行了四分之一左右,我得到了一个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
会有所作为?