Member 13245297 Ответов: 1

C# concurrentqueue показывает исключение из памяти после запуска в течение нескольких часов


Привет. Я работаю с данными, которые генерируются каждую секунду. Я пытаюсь использовать ConcurrentQueue для постановки в очередь этого содержимого. Я добавил задачу, которая проверяет, превышает ли количество очередей 500. Если он больше 500, он удаляет содержимое в массив, и я отправляю массив. Вот как работает мое приложение. Но пробежав несколько часов, я получил следующее сообщение:
at (wrapper alloc) System.Object.AllocVector(intptr,intptr)
  at System.Collections.Concurrent.ConcurrentQueue`1+Segment[T]..ctor (System.Int32 boundedLength) [0x00006] in <f56c876907e742b0aa586f051fcce845>:0 
  at System.Collections.Concurrent.ConcurrentQueue`1[T].EnqueueSlow (T item) [0x00051] in <f56c876907e742b0aa586f051fcce845>:0 
  at System.Collections.Concurrent.ConcurrentQueue`1[T].Enqueue (T item) [0x00010] in <f56c876907e742b0aa586f051fcce845>:0 
Пожалуйста, помогите мне. Дайте мне предложения Соммы, чтобы решить эту проблему. Должен ли я использовать систему.Дженерик.Очередь вместо ConcurrentQueue?
Я использую следующие шаги:
1. считывает данные с последовательного порта и ставит их в очередь
ConcurrentQueue<int> queue1 = new ConcurrentQueue<int>();
queue1.enqueue(values)
2. Для извлечения я использую следующие задания
public async Task PublishMessage()
{
int waittime =1;
if (waittime != 0)
{
do
{
double[] testarray=new double[512];
if(queue1.Count>=512)
{
wavetest = new double[512];
for (int k = 0; k < 512; k++)
{
queue1.TryDequeue(out testarray[k]);

}
SendMessage(testarray);
}
await Task.Delay(waittime);

}
while (true);
}

}
Спасибо

Что я уже пробовал:

Я попробовал посмотреть, увеличивается ли очередь со временем. Но нет. Количество очередей составляло около 250 человек в каждой. Она не увеличивалась быстро со временем.

Wendelius

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

Member 13245297

Я делаю следующее:
1. считывает данные с последовательного порта и ставит их в очередь
Коллекции concurrentqueue И Л;int> В queue1 = новые коллекции concurrentqueue И Л;int&ГТ;();
queue1.enqueue(значения)
2. Для извлечения я использую следующие задания

публичная асинхронная задача PubMessage()
{
int waittime =1;
если (время ожидания != 0)
{
делать
{
double[] testarray=новый double[512];
if(queue1.Count>=512)
{
wavetest = новый двойной[512];
for (int k = 0; k < 512; k++)
{
queue1.TryDequeue(out testarray[k]);

}
SendMessage(testarray);
}
жду задания.Задержка(время ожидания);

}
в то время как (правда);
}

}

Patrice T

Воспользуйся Улучшить вопрос чтобы обновить ваш вопрос.
Чтобы каждый мог обратить внимание на эту информацию.

Member 13245297

Спасибо что ответили

1 Ответов

Рейтинг:
2

Stryder_1

Есть две вещи, которые я вижу, что приведет к потере памяти:

1. Во-первых, вы выделяете новый double[512] каждый раз, когда цикл do-while повторяется. Если вы переместите этот оператор в блок if, который проверяет наличие count>=512, то теперь он будет выделять память только тогда, когда вы достигнете минимального количества.

2. Во-вторых, это асинхронная задача. Это называется несколько раз? Если это так, то цикл do-while настраивается как бесконечный цикл. Каждый раз, когда это вызывается, он запускает новый цикл, но все предыдущие вызовы все равно будут иметь свои циклы выполнения.

Я также не вижу необходимости в строке "wavetest = new double[512];"


Member 13245297

Привет. Спасибо, что указал на эту ошибку. Я исправлю это. Я не мог правильно понять второй пункт. Прямо сейчас я фактически запускаю задачу PubMessage,когда моя программа начинает выполнение, и она будет проверять, выполняется ли условие(Count>512) каждую миллисекунду, и если условие выполнено, то она отправит сообщение. Таким образом, моя основная программа будет ставить в очередь все точки данных, полученные каждую миллисекунду, а задача PubMessage будет периодически удалять из очереди содержимое и отправлять его. У вас есть какие-нибудь предложения по оптимизации моего решения? Спасибо

Stryder_1

Поскольку вы вызываете эту функцию только один раз в своем приложении, вы, вероятно, не будете касаться пункта #2. Однако если вы хотите узнать об этом больше, ищите асинхронное программирование.

Из того, что я могу сказать, вам действительно не нужен новый массив, выделяемый с каждым минимальным количеством. Вместо этого повторно используйте уже созданный массив. Можно объявить массив, прежде чем делать-цикл while. Затем вместо того, чтобы создавать экземпляр массива с каждым циклом, сбросьте значения в массиве на число, которое вы не получили бы от последовательного порта. Например, если вы не ожидаете отрицательных значений, вы можете инициализировать каждое значение массива с помощью -1. Это позволит исключить обработку распределения/освобождения для каждой итерации цикла.