C# 垃圾收集器在.NET核心API中未被调用?
我使用postman连续调用了大约100次API方法。运行两次后,内存图从100mb变为400mb。整个过程中没有一个黄色标记: 然后我在控制器中添加了这两行:C# 垃圾收集器在.NET核心API中未被调用?,c#,asp.net,.net,performance,garbage-collection,C#,Asp.net,.net,Performance,Garbage Collection,我使用postman连续调用了大约100次API方法。运行两次后,内存图从100mb变为400mb。整个过程中没有一个黄色标记: 然后我在控制器中添加了这两行: GC.Collect(2, GCCollectionMode.Forced, true); GC.WaitForPendingFinalizers(); 图中显示: 而且,内存消耗的增加不会超过150mb 这可能是什么原因 下面几行实际上是做什么的?我们正面临内存泄漏 GC.Collect(2, GCCollectionMo
GC.Collect(2, GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();
图中显示:
而且,内存消耗的增加不会超过150mb
这可能是什么原因
下面几行实际上是做什么的?我们正面临内存泄漏
GC.Collect(2, GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();
控制器有一个调用服务层的操作方法,该服务层调用DataAccess层,如下所示:
public async Task<PackingSlips> GetAllPackingSlipsByStatus(long statusCode, int offset, int fetch)
{
using (SqlConnection sqlConnection = (SqlConnection)sqlHelper.CreateConnection())
{
PackingSlips packingSlips = new PackingSlips();
List<PackingSlipDetails> packingSlipDetailsList = new List<PackingSlipDetails>();
sqlConnection.Open();
SqlCommand cmd = new SqlCommand(Constants.GetAllPackingSLipsByStatus, sqlConnection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@CreatedBy", SqlDbType.NVarChar).Value = _gepservice.GetUserContext().UserId;
cmd.Parameters.Add("@DocumentStatus", SqlDbType.Int).Value = statusCode;
cmd.Parameters.Add("@OffsetRows", SqlDbType.NVarChar).Value = offset;
cmd.Parameters.Add("@FetchRows", SqlDbType.NVarChar).Value = fetch;
var refCountdr = (RefCountingDataReader)(await sqlHelper.ExecuteReaderAsync(cmd));
var sqlDr = (SqlDataReader)refCountdr.InnerReader;
if (sqlDr != null)
{
while (sqlDr.Read())
{
PackingSlipDetails packingSlipDetails = new PackingSlipDetails
{
Id = Convert.ToInt32(sqlDr[Constants.Id]),
FileName = Convert.ToString(sqlDr[Constants.FileName]),
FileUri = Convert.ToString(sqlDr[Constants.FileURI]),
PONumber = Convert.ToString(sqlDr[Constants.DocumentNumber]) == Constants.Zero ? "-" : Convert.ToString(sqlDr[Constants.DocumentNumber]),
UploadDate = Convert.IsDBNull(sqlDr[Constants.UploadDate]) ? DateTime.UtcNow : Convert.ToDateTime(sqlDr[Constants.UploadDate]),
FileStatus = (Convert.ToInt16(sqlDr[Constants.FileStatus])),
ReceiptNumber = Convert.ToString(sqlDr[Constants.ReceiptNumber]),
CreatedBy = _gepservice.GetUserContext().UserId
};
if (packingSlipDetails.PONumber == null || packingSlipDetails.PONumber == "")
packingSlipDetails.PONumber = "-";
packingSlipDetailsList.Add(packingSlipDetails);
packingSlips.TotalRows = Convert.ToInt32(sqlDr[Constants.TotalRows]);
}
}
packingSlips.PackingSlipDetails = packingSlipDetailsList;
return packingSlips;
}
}
公共异步任务GetAllPackingSlipsByStatus(长状态码、整数偏移量、整数提取)
{
使用(SqlConnection SqlConnection=(SqlConnection)sqlHelper.CreateConnection())
{
装箱单装箱单=新装箱单();
List packingSlipDetailsList=新列表();
sqlConnection.Open();
SqlCommand cmd=新的SqlCommand(Constants.GetAllPackingSLipsByStatus,sqlConnection);
cmd.CommandType=CommandType.storedProcess;
Add(“@CreatedBy”,SqlDbType.NVarChar).Value=\u gepservice.GetUserContext().UserId;
cmd.Parameters.Add(“@DocumentStatus”,SqlDbType.Int).Value=statusCode;
cmd.Parameters.Add(“@OffsetRows”,SqlDbType.NVarChar).Value=offset;
Add(“@FetchRows”,SqlDbType.NVarChar).Value=fetch;
var refCountdr=(RefCountingDataReader)(等待sqlHelper.ExecuteReaderAsync(cmd));
var sqlDr=(SqlDataReader)refCountdr.InnerReader;
if(sqlDr!=null)
{
while(sqlDr.Read())
{
打包详细信息打包详细信息=新打包详细信息
{
Id=Convert.ToInt32(sqlDr[Constants.Id]),
FileName=Convert.ToString(sqlDr[Constants.FileName]),
FileUri=Convert.ToString(sqlDr[Constants.FileUri]),
PONumber=Convert.ToString(sqlDr[Constants.DocumentNumber])==Constants.Zero?-“:Convert.ToString(sqlDr[Constants.DocumentNumber]),
UploadDate=Convert.IsDBNull(sqlDr[Constants.UploadDate])?DateTime.UtcNow:Convert.ToDateTime(sqlDr[Constants.UploadDate]),
FileStatus=(Convert.ToInt16(sqlDr[Constants.FileStatus]),
ReceiptNumber=Convert.ToString(sqlDr[Constants.ReceiptNumber]),
CreatedBy=\u gepservice.GetUserContext().UserId
};
if(packingSlipDetails.PONumber==null | | packingSlipDetails.PONumber==“”)
packingSlipDetails.PONumber=“-”;
packingSlipDetails.Add(packingSlipDetails);
packingships.TotalRows=Convert.ToInt32(sqlDr[Constants.TotalRows]);
}
}
packingSlips.PackingSlipDetails=PackingSlipDetails列表;
退货装箱单;
}
}
尝试添加sqlDr.Close()在while(sqlDr.Read())
循环之后
如果关闭datareader还没有解决您的问题
您可能面临的问题是当前线程可能被锁定,因为GC当前正在等待所有终结器完成
由于以下陈述。
GC.WaitForPendingFinalizers()代码>
创建一个新线程,该线程将等待一段时间,并在第一个线程仍然挂起时中断它如何使用aroundSqlCommand
和SqlDataReader
?@FrankNielsen我认为使用在中包装连接就足够了。不是吗?所有具有IDisposable
的东西都需要使用
。众所周知的异常是,SqlCommand实际上不需要被释放。这里不需要使用RefCountingDataReader
。@FrankNielsen我将using添加到SqlDataReader和SqlCommand中,但实际上没有什么区别。我仍然看不到一个垃圾收集器的黄色标记,内存一直在增加。显然不是这样,不可能在其他线程上执行time
线程操作。要么像Henk Holterman所说的那样没有问题,要么如果有泄漏,就追踪它。感谢@Frank的输入…目的不是给线程计时,而是确保当前线程没有被永久锁定。正如我前面提到的,关闭dataReader应该可以解决问题。尤其是在它的利用率低于while循环之后