Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何处理BackgroundWorker DoWork eventhandler中的内存泄漏_C#_Winforms_Memory Leaks_Datagridview_Backgroundworker - Fatal编程技术网

C# 如何处理BackgroundWorker DoWork eventhandler中的内存泄漏

C# 如何处理BackgroundWorker DoWork eventhandler中的内存泄漏,c#,winforms,memory-leaks,datagridview,backgroundworker,C#,Winforms,Memory Leaks,Datagridview,Backgroundworker,我正在创建一个应用程序(logviewer),它将显示xml文件中的日志。注意:每个xml文件可以有一个或多个记录。我的应用程序必须在DatagridView控件中将每个记录显示为一行 基本上,它将执行以下任务: 1.从Do_Work=>解析每个xml文件并将记录添加到列表中。 2.如果列表大小达到100,则调用ProgressChanged事件以使用100条记录更新UI(DataGridView)。 3.重复此过程,直到所有xml文件中的所有记录都附加到UI(DataGridView) 实施:

我正在创建一个应用程序(logviewer),它将显示xml文件中的日志。注意:每个xml文件可以有一个或多个记录。我的应用程序必须在DatagridView控件中将每个记录显示为一行

基本上,它将执行以下任务:

1.从Do_Work=>解析每个xml文件并将记录添加到列表中。
2.如果列表大小达到100,则调用ProgressChanged事件以使用100条记录更新UI(DataGridView)。
3.重复此过程,直到所有xml文件中的所有记录都附加到UI(DataGridView)

实施:

DoWork将每个记录添加到原始列表中,一旦列表计数变为100,它将创建一个新的列表集合并调用ProgressChanged事件

详情如下:

bWorkerReadXmlLogs.ReportProgress(0, new List<XmlLogRecord>(lstXmlLogRecords)); //memory leak
但问题是当
ProgressChanged
事件处理程序将所有100条记录追加到
DataGridView
控件时,
DoWork
(因为DoWork和ProgressChanged事件之间没有同步)将其清除(原始集合)若要添加另一组记录并
ProgressChanged
将引发集合修改异常

现在我需要知道如何通过从原始集合复制/创建新集合来释放内存:

我的分析: 我可以传递原始集合引用变量,并在
DoWork
后台线程中等待更多时间,以确保主/UI线程将所有100条记录添加到DataGridView,但这不是最佳解决方案,并且如果用户在某些低端配置中运行应用程序,则可能无法确保它始终工作

示例代码:

private void bWorkerReadXmlLogs_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {                               
        //declare a xmlLogRecords list to hold the list of log records to be displayed on the UI
        List<XmlLogRecord> lstXmlLogRecords = new List<XmlLogRecord>();

        //loop through the records sent by the GetLogDetails() function and add it to the list
        foreach (XmlLogRecord record in GetLogDetails(path))
        {
            //cancel the background thread if the cancel was requested from the user.
            if (bWorkerReadXmlLogs.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
            //add log record to the list
            lstXmlLogRecords.Add(record);

            /*if the list contains 100 items then invoke the progresschanged event 
            where it appends the 100 items into the LogViewer UI (DataGridView)*/
            if (lstXmlLogRecords.Count % 100 == 0)
            {
                //block/wait on background thread so that processor allocates some cycles to work on UI/Main thread to update the records on the DatagridView
                Thread.Sleep(200); 


                bWorkerReadXmlLogs.ReportProgress(0, new List<XmlLogRecord>(lstXmlLogRecords));//Memory Leak here,if i pass original collection reference it works but DoWork clears it immediatly to add new set of records

                //clear the List to start/add remaining items.
                lstXmlLogRecords.Clear();
            }
        }

        //invoke the ProgressChanged Event for updating the DataGridView if the List contains less than 100 items greater than 0 items
        if (lstXmlLogRecords.Count > 0)
        {                
            //Invoke ProgressChanged Event to update the records on the DataGridView
            bWorkerReadXmlLogs.ReportProgress(0, lstXmlLogRecords);
        }
    }
    catch (Exception ex)
    {
        Write_Trace(ex.Message);
    }
}

private void bWorkerReadXmlLogs_ProgressChanged(object sender, ProgressChangedEventArgs e)
{           
        try
        {
            var rowIndex = 0;
            if (e.UserState is List<XmlLogRecord>)
            {
                //Cast the UserState object into the List<XmlLogRecord>
                var records = e.UserState as List<XmlLogRecord>;

                //iterate over all the records sent from DoWork event and append the each record into the LogViewer control DataGridView UI
                foreach (var record in records)
                {
                    //get the next row Index where the new row has to be placed.
                    rowIndex = dgvLogViewer.Rows.Count;

                    //add an emtpy row to add the empty cells into it
                    dgvLogViewer.Rows.Add();

                    //set the LogViewer properties if not set already
                    if (!IsLogviewerPropertiesSet)
                    {
                        SetLogViewerProperties();
                    }

                    //Disable the Column selection for image columns
                    DisableImageColumnsSelection(rowIndex);

                    //Add Data for normal or text cells into the LogViewer Control (DatagridView)
                    AddLogviewerTextCells(rowIndex, record);

                    //Add Icons in Image Columns into the LogViewer control (DataGridView) 
                    AddLogviewerImageCells(rowIndex, record);
                }

                //Sort the LogViewer control (DataGridView) by Datetime column(Index = 2) in Descending order.
                dgvLogViewer.Sort(dgvLogViewer.Columns[MKeys.DTTIME], ListSortDirection.Descending);
                dgvLogViewer.Columns[MKeys.DTTIME].HeaderCell.SortGlyphDirection = SortOrder.Descending;
                if (!IsLogviewerSortingDone)
                {
                    //call selectedindex changed event of the selected record in the datagridview
                    dgvLogViewer_SelectionChanged(null, null);
                    IsLogviewerSortingDone = true;
                }
            }
        }
        catch (Exception ex)
        {                   
            Write_Trace(ex.Message);
        }
    }
}
private void bWorkerReadXmlLogs\u DoWork(对象发送方,DoWorkerVentargs e)
{
尝试
{                               
//声明xmlLogRecords列表以保存要在UI上显示的日志记录列表
List lstXmlLogRecords=新列表();
//循环遍历GetLogDetails()函数发送的记录,并将其添加到列表中
foreach(GetLogDetails(路径)中的XmlLogRecord记录)
{
//如果用户请求取消,则取消后台线程。
if(bWorkerReadXmlLogs.CancellationPending)
{
e、 取消=真;
回来
}
//将日志记录添加到列表中
lstXmlLogRecords.Add(记录);
/*如果列表包含100项,则调用progresschanged事件
它将100项附加到LogViewer UI(DataGridView)中*/
if(lstXmlLogRecords.Count%100==0)
{
//阻塞/等待后台线程,以便处理器分配一些周期在UI/主线程上工作,以更新DatagridView上的记录
睡眠(200);
bWorkerReadXmlLogs.ReportProgress(0,新列表(lstXmlLogRecords));//此处内存泄漏,如果我传递原始集合引用,它会工作,但DoWork会立即清除它以添加新的记录集
//清除列表以启动/添加剩余项目。
lstXmlLogRecords.Clear();
}
}
//如果列表包含少于100项且大于0项,则调用ProgressChanged事件更新DataGridView
如果(lstXmlLogRecords.Count>0)
{                
//调用ProgressChanged事件以更新DataGridView上的记录
ReportProgress(0,lstXmlLogRecords);
}
}
捕获(例外情况除外)
{
写入跟踪(例如消息);
}
}
私有void bWorkerReadXmlLogs_ProgressChanged(对象发送方,ProgressChangedEventArgs e)
{           
尝试
{
var-rowIndex=0;
如果(例如,用户状态为列表)
{
//将UserState对象强制转换到列表中
var记录=e.UserState作为列表;
//迭代从DoWork事件发送的所有记录,并将每个记录附加到LogViewer控件DataGridView UI中
foreach(记录中的var记录)
{
//获取必须放置新行的下一行索引。
rowIndex=dgvLogViewer.Rows.Count;
//添加emtpy行以将空单元格添加到其中
dgvLogViewer.Rows.Add();
//设置LogViewer属性(如果尚未设置)
如果(!IsLogViewerPropertieSet)
{
SetLogViewerProperties();
}
//禁用图像列的列选择
禁用图像列选择(行索引);
//将普通单元格或文本单元格的数据添加到LogViewer控件(DatagridView)
AddLogviewerTextCells(行索引,记录);
//将图像列中的图标添加到LogViewer控件(DataGridView)
AddLogviewerImageCells(行索引,记录);
}
//按Datetime列(索引=2)降序排列LogViewer控件(DataGridView)。
dgvLogViewer.Sort(dgvLogViewer.Columns[MKeys.DTTIME],ListSortDirection.Descending);
dgvLogViewer.Columns[MKeys.DTTIME].HeaderCell.SortGlyphDirection=SortOrder.Descending;
如果(!IsLogviewerSortingDone)
{
//调用datagridview中选定记录的selectedindex changed事件
dgvLogViewer_SelectionChanged(空,空);
IsLogviewerSortingDone=true;
}
}
}
捕获(例外情况除外)
{                   
写入跟踪(例如消息);
}
}
}

@Downvoter:如果我的帖子有任何问题,请告诉我,以便我可以处理。您使用的是哪个.NET版本?@YuvalItzchakov:private void bWorkerReadXmlLogs_DoWork(object sender, DoWorkEventArgs e) { try { //declare a xmlLogRecords list to hold the list of log records to be displayed on the UI List<XmlLogRecord> lstXmlLogRecords = new List<XmlLogRecord>(); //loop through the records sent by the GetLogDetails() function and add it to the list foreach (XmlLogRecord record in GetLogDetails(path)) { //cancel the background thread if the cancel was requested from the user. if (bWorkerReadXmlLogs.CancellationPending) { e.Cancel = true; return; } //add log record to the list lstXmlLogRecords.Add(record); /*if the list contains 100 items then invoke the progresschanged event where it appends the 100 items into the LogViewer UI (DataGridView)*/ if (lstXmlLogRecords.Count % 100 == 0) { //block/wait on background thread so that processor allocates some cycles to work on UI/Main thread to update the records on the DatagridView Thread.Sleep(200); bWorkerReadXmlLogs.ReportProgress(0, new List<XmlLogRecord>(lstXmlLogRecords));//Memory Leak here,if i pass original collection reference it works but DoWork clears it immediatly to add new set of records //clear the List to start/add remaining items. lstXmlLogRecords.Clear(); } } //invoke the ProgressChanged Event for updating the DataGridView if the List contains less than 100 items greater than 0 items if (lstXmlLogRecords.Count > 0) { //Invoke ProgressChanged Event to update the records on the DataGridView bWorkerReadXmlLogs.ReportProgress(0, lstXmlLogRecords); } } catch (Exception ex) { Write_Trace(ex.Message); } } private void bWorkerReadXmlLogs_ProgressChanged(object sender, ProgressChangedEventArgs e) { try { var rowIndex = 0; if (e.UserState is List<XmlLogRecord>) { //Cast the UserState object into the List<XmlLogRecord> var records = e.UserState as List<XmlLogRecord>; //iterate over all the records sent from DoWork event and append the each record into the LogViewer control DataGridView UI foreach (var record in records) { //get the next row Index where the new row has to be placed. rowIndex = dgvLogViewer.Rows.Count; //add an emtpy row to add the empty cells into it dgvLogViewer.Rows.Add(); //set the LogViewer properties if not set already if (!IsLogviewerPropertiesSet) { SetLogViewerProperties(); } //Disable the Column selection for image columns DisableImageColumnsSelection(rowIndex); //Add Data for normal or text cells into the LogViewer Control (DatagridView) AddLogviewerTextCells(rowIndex, record); //Add Icons in Image Columns into the LogViewer control (DataGridView) AddLogviewerImageCells(rowIndex, record); } //Sort the LogViewer control (DataGridView) by Datetime column(Index = 2) in Descending order. dgvLogViewer.Sort(dgvLogViewer.Columns[MKeys.DTTIME], ListSortDirection.Descending); dgvLogViewer.Columns[MKeys.DTTIME].HeaderCell.SortGlyphDirection = SortOrder.Descending; if (!IsLogviewerSortingDone) { //call selectedindex changed event of the selected record in the datagridview dgvLogViewer_SelectionChanged(null, null); IsLogviewerSortingDone = true; } } } catch (Exception ex) { Write_Trace(ex.Message); } } }