Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.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# 无法检测的内存泄漏_C#_Garbage Collection - Fatal编程技术网

C# 无法检测的内存泄漏

C# 无法检测的内存泄漏,c#,garbage-collection,C#,Garbage Collection,我有一个Stock类,它从一个文件(大约100MB)加载大量的股票数据历史记录。我有一个Pair类,它接受两个Stock对象,计算它们之间的一些统计关系,然后将结果写入文件 在我的主要方法中,我有一个循环遍历一组股票(大约500只)。它创建两个库存对象,然后从两个库存对象中创建一个配对对象。在这一点上,成对的计算被写入到文件中,我已经完成了对对象的处理。我需要释放内存以便继续下一次计算 除了将3个对象设置为null之外,我还在循环末尾添加了以下两行: GC.Collect(GC.MaxGener

我有一个
Stock
类,它从一个文件(大约100MB)加载大量的股票数据历史记录。我有一个
Pair
类,它接受两个
Stock
对象,计算它们之间的一些统计关系,然后将结果写入文件

在我的主要方法中,我有一个循环遍历一组股票(大约500只)。它创建两个库存对象,然后从两个库存对象中创建一个配对对象。在这一点上,成对的计算被写入到文件中,我已经完成了对对象的处理。我需要释放内存以便继续下一次计算

除了将3个对象设置为null之外,我还在循环末尾添加了以下两行:

GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
跨过这两行似乎只是从每个循环迭代分配的200-300MB中释放出50MB(从任务管理器查看)

该程序在给我一个系统内存不足异常之前,会执行大约八到十对操作。内存使用率稳步增加,直到崩溃到1.5 GB左右。(这是一台运行Win7 Ultimate的8 GB计算机)

我在垃圾收集方面没有太多经验。我做错什么了吗

这是您询问后我的代码:(注意:程序有两种模式,1>添加模式,在其中向系统添加新对。2>常规模式,根据
filesystemwatcher
事件实时更新对文件。股票数据由名为QCollector的外部应用程序更新。)

这是在添加模式下运行的
MainForm
中的段:

foreach (string line in PairList)
{
    string[] tokens = line.Split(',');

    stockA = new Stock(QCollectorPath, tokens[0].ToUpper()); 
    stockB = new Stock(QCollectorPath, tokens[1].ToUpper()); 

    double ratio = double.Parse(tokens[2]);
    Pair p = new Pair(QCollectorPath, stockA, stockB, ratio);

    // at this point the pair is written to file (constructor handles this)        

    // commenting out the following lines of code since they don't fix the problem
    // stockA = null;
    // stockB = null;
    // p = null;

    // refraining from forced collection since that's not the problem
    // GC.Collect(GC.MaxGeneration);
    // GC.WaitForPendingFinalizers();

    // so far this is the only way i can fix the problem by setting the pair classes
    // references to StockA and StockB to null
    p.Kill();
}
我正在根据请求添加更多代码:
Stock
Pair
TimeSeries
的子类,它们具有相同的功能

public abstract class TimeSeries {
     protected List<string> data;

     // following create class must be implemented by subclasses (stock, pair, etc...)
     // as each class is created differently, although their data formatting is identical
     protected void List<string> Create();

     // . . . 

     public void LoadFromFile()
     {
          data = new List<string>();

          List<StreamReader> srs = GetAllFiles();

          foreach (StreamReader sr in srs)
          {
               List<string> temp = new List<string>();
               temp = TurnFileIntoListString(sr);
               data = new List<string>(temp.Concat(data));
               sr.Close()
          }
     }

     // uses directory naming scheme (according to data month/year) to find files of a symbol
     protected List<StreamReader> GetAllFiles()...

     public static List<string> TurnFileIntoListString(StreamReader sr)
     {
          List<string> list = new List<string>();
          string line;
          while ((line = sr.ReadLine()) != null)
               list.Add(line);
          return list;
     }

     // this is the only mean to access a TimeSeries object's data
     // this is to prevent deadlocks by time consuming methods such as pair's Create

     public string[] GetListCopy()
     {
          lock (data)
          {
               string[] listCopy = new string[data.count];
               data.CopyTo(listCopy);
               return listCopy();
          }
     }
}

public class Stock : TimeSeries
{
     public Stock(string dataFilePath, string symbol, FileSystemWatcher fsw = null)
     {
          DataFilePath = dataFilePath;
          Name = symbol.ToUpper();
          LoadFromFile();
          // to update stock data when external app updates the files
          if (fsw != null) fsw.Changed += FileSystemEventHandler(fsw_Changed);
     }

     protected void List<string> Create()
     {
          // stock files created by external application
     }


     // . . . 
}

public class Pair : TimeSeries {
     public Pair(string dataFilePath, Stock stockA, Stock stockB, double ratio)
     {
          // assign parameters to local members
          // ...         

          if (FileExists())
               LoadFromFile();
          else
             Create();
     }

     protected override List<string> Create()
     {
          // since stock can get updated by fileSystemWatcher's event handler
          // a copy is obtained from the stock object's data 
          string[] listA = StockA.GetListCopy();
          string[] listB = StockB.GetListCopy();
          List<string> listP = new List<string>();

          int i, j;
          i = GetFirstValidBar(listA);
          j = GetFirstValidBar(listB);
          DateTime dtA, dtB;

          dtA = GetDateTime(listA[i]);
          dtB = GetDateTime(listB[j]);

          // this hidden segment adjusts i and j until they are starting at same datetime
          // since stocks can have different amount of data

          while (i < listA.Count() && j < listB.Count)
          {
              double priceA = GetPrice(listA[i]);
              double priceB = GetPrice(listB[j]);
              double priceP = priceA * ratio - priceB;
              listP.Add(String.Format("{0},{1:0.00},{2:0.00},{3:0.00}"
                   , dtA
                   , priceP
                   , priceA
                   , priceB
              );
              if (i < j)
                   i++;
              else if (j < i)
                   j++;
              else
              {
                   i++; 
                   j++;
              }
          }
     }

     public void Kill()
     {
         data = null;
         stockA = null;
         stockB = null;
     }
 }
公共抽象类时间序列{
受保护名单数据;
//以下创建类必须由子类(stock、pair等)实现
//虽然每个类的数据格式相同,但它们的创建方式不同
受保护的无效列表创建();
// . . . 
公共void LoadFromFile()
{
数据=新列表();
List srs=GetAllFiles();
foreach(srs中的StreamReader sr)
{
列表温度=新列表();
temp=TurnFileIntoListString(sr);
数据=新列表(临时混凝土(数据));
高级关闭()
}
}
//使用目录命名方案(根据数据月/年)查找符号的文件
受保护的列表GetAllFiles()。。。
公共静态列表TurnFileIntoListString(StreamReader sr)
{
列表=新列表();
弦线;
而((line=sr.ReadLine())!=null)
列表。添加(行);
退货清单;
}
//这是访问TimeSeries对象数据的唯一方法
//这是为了通过耗时的方法(如pair的Create)防止死锁
公共字符串[]GetListCopy()
{
锁(数据)
{
string[]listCopy=新字符串[data.count];
data.CopyTo(listCopy);
返回listCopy();
}
}
}
公共类股票:TimeSeries
{
公开股票(字符串dataFilePath,字符串符号,FileSystemWatcher fsw=null)
{
DataFilePath=DataFilePath;
Name=symbol.ToUpper();
LoadFromFile();
//当外部应用程序更新文件时更新股票数据
如果(fsw!=null)fsw.Changed+=FileSystemEventHandler(fsw\u Changed);
}
受保护的无效列表创建()
{
//由外部应用程序创建的库存文件
}
// . . . 
}
公共类对:TimeSeries{
公共对(字符串数据文件路径、股票A、股票B、双倍比率)
{
//将参数指定给本地成员
// ...         
如果(FileExists())
LoadFromFile();
其他的
创建();
}
受保护的覆盖列表创建()
{
//因为股票可以通过fileSystemWatcher的事件处理程序进行更新
//从股票对象的数据中获取副本
字符串[]listA=StockA.GetListCopy();
字符串[]listB=StockB.GetListCopy();
List listP=新列表();
int i,j;
i=GetFirstValidBar(列表A);
j=GetFirstValidBar(列表B);
日期时间dtA,dtB;
dtA=GetDateTime(列表A[i]);
dtB=GetDateTime(listB[j]);
//此隐藏段调整i和j,直到它们同时开始
//因为股票可以有不同数量的数据
而(i
您的内存泄漏在这里:

if (fsw != null) fsw.Changed += FileSystemEventHandler(fsw_Changed);
只要FileSystemWatcher处于活动状态,stock对象的实例就会保存在内存中,因为它正在响应FileSystemWatcher的事件

我认为您希望在其他地方实现该事件,或者在代码的其他地方添加一个:

if (fsw != null) fsw.Changed -= fsw_Changed;
考虑到代码的编写方式,在批量处理完成的情况下,可能需要在没有FileSystemWatcher的情况下调用stock对象

在您发布的原始代码中,Stock类的构造函数被FileSystemWatcher调用