StackOverFlowException - но очевидно НИКАКОЙ рекурсии / бесконечного цикла - PullRequest
1 голос
/ 08 января 2011

Я теперь заблокирован этой проблемой весь день, читаю тысячи результатов Google, но, похоже, ничто не отражает мою проблему или даже не подходит к ней ... Я надеюсь, что у любого из вас есть толчок в правильном направлении дляme.

Я написал клиент-серверное приложение (так что больше похоже на 2 приложения) - клиент собирает данные о своей системе, а также снимок экрана, сериализует все это в поток XML (изображение в видеbyte [] - array]) и регулярно отправляет это на сервер.Сервер получает поток (через tcp), десериализует xml в информационный объект и показывает информацию в форме окна.Этот процесс работает стабильно в течение 20-25 минут с интервалом отправки 3 секунды.При наблюдении за использованием памяти нет ничего существенного, в том числе и стабильного.Но после этих 20-25 минут сервер создает исключение StackOverflowException в точке, где десериализует tcp-поток, особенно при установке свойства Image из массива byte [].

Я тщательно искал рекурсивный или бесконечныйциклы, и что касается того, что это происходит после тысяч успешных интервалов, я вряд ли мог себе это представить.

    public byte[] ImageBase
    {
        get
        {
            MemoryStream ms = new MemoryStream();
            _screen.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            return ms.GetBuffer();
        }
        set
        {
            if (_screen != null) _screen.Dispose(); //preventing well-known image memory leak
            MemoryStream ms = new MemoryStream(value);
            try
            {
                _screen = Image.FromStream(ms); //<< EXCEPTION THROWING HERE
            }
            catch (StackOverflowException ex) //thx to new CLR management this wont work anymore -.-
            {
                Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
            }
            ms.Dispose();
            ms = null;
        }
    }

Я надеюсь, что больше кода будет ненужным, или он может стать очень сложным ...

Пожалуйста, помогите, я понятия не имею больше

thx Крис

Ответы [ 3 ]

3 голосов
/ 08 января 2011

Я подозреваю, что это не код, который вы разместили, а код, который читает из потока TCP, который увеличивает стек. То, что солома, ломающая спину верблюда, происходит во время Image.FromStream, вероятно, не имеет значения. Я часто видел, как люди пишут код обработки сокетов, содержащий код, вызывающий себя (иногда косвенно, например, A -> B -> A -> B). Вы должны проверить этот код и опубликовать его здесь, чтобы мы могли на него посмотреть.

3 голосов
/ 08 января 2011

Возможно, вы захотите прочитать это. Загрузка изображения из потока без сохранения потока открытым

Кажется возможным, что потоки поддерживаются в стеке или каком-либо другом объекте, который в конечном итоге уносит стек.

Тогда я бы предложил просто удерживать byte[] и ждать до последнего возможного момента, чтобы расшифровать его и нарисовать. затем немедленно утилизируйте изображение. Ваш get / set просто установит / получит byte[]. Затем вы реализуете пользовательскую процедуру рисования, которая будет декодировать текущую byte[] и рисовать ее, стараясь не удерживать больше ресурсов, чем необходимо.

Обновление

Если есть способ, которым вы можете получить нам полную трассировку стека, мы могли бы помочь в дальнейшем. Я начинаю думать, что это не та проблема, которую я описал. Я создал пример программы, которая создала 10 000 изображений точно так же, как вы делаете это в своем сеттере, и проблем не было. Если вы отправляете изображение каждые 3 секунды, это 30 изображений в минуту и ​​20 минут, что составляет всего 600 изображений.

Я очень заинтересован в решении этого вопроса. Я вернусь к этому позже.

Есть несколько возможностей, однако, удаленных.

  • Image.FromStream пытается обработать недопустимый / поврежденный байт [], и этот метод каким-то образом использует рекурсию для декодирования растрового изображения. Весьма маловероятно.
  • Исключение не выдается там, где вы думаете. Полная трассировка стека, если возможно, будет очень полезна. Как вы заявили, вы не можете поймать исключение StackOverflowException. Я считаю, что для этого есть условия, если вы запускаете его через отладчик.
1 голос
/ 08 января 2011

Я не уверен, что это актуально, но в документации MSDN для Image.FromStream указано, что Вы должны держать поток открытым в течение всего времени жизни изображения.

...