Сборщик мусора не вызывается. NET Core API? - PullRequest
0 голосов
/ 19 января 2020

Я использовал почтальон для вызова метода API около 100 раз подряд. График памяти увеличился с 100 до 400 Мб после двухкратного запуска. И там не было ни одной желтой отметки:

enter image description here

Затем я добавил эти две строки в мой контроллер:

GC.Collect(2, GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();

И график выглядел:

enter image description here

Кроме того, потребление памяти не превысило 150 МБ

Что может быть причина этого?

Что на самом деле делают следующие строки? Мы сталкиваемся с утечками памяти.

   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;
            }
        }

1 Ответ

0 голосов
/ 19 января 2020

Попробуйте добавить sqlDr.Close(); после цикла while (sqlDr.Read()). Если закрытие устройства чтения данных не решило вашу проблему.

Проблема, с которой вы можете столкнуться, заключается в том, что текущий поток может быть заблокирован, поскольку G C в настоящее время ожидает завершения всех финализаторов. GC.WaitForPendingFinalizers();

Создать новый поток, который будет некоторое время ждать, и прервать первый поток, если он все еще приостановлен

...