OutOfMemoryException с использованием истекшего по таймеру события с #

Я получаю исключение нехватки памяти при использовании времени. Может ли это иметь какое-то отношение к использованию таймера в структуре - возможно ли иметь таймер в структуре, например, ниже:

 public struct SessionStruct 
{
    private bool _isElapsed;
    public bool isElapsed
    {
        get{return _isElapsed;}
        set { _isElapsed = value; }
    }
    public string sessionID
    {
        get;
        set;
    }
    public DateTime time
    {
        get;
        set;
    }

    public Timer timer
    { get; set; }

};

Это обработчик прошедшего события:

static void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        req = "<Request><ID>1234567</ID><type>10</type><attribute>" + session1.sessionID + "|</attribute></Request>";}

[РЕДАКТИРОВАТЬ]

Вот код для создания и установки значений - это только часть ...

        public Request(string request, Database db)
    {

// мгновенное создание s = new SessionStruct (); s.timer = новый таймер (60000); s.timer.Enabled = true; // db = new Database (); попробуйте {Debug.WriteLine ("Начат новый запрос"); doc = новый XmlDocument (); doc.LoadXml (запрос); строковый атрибут = ""; // строка sessionID = ""; ArrayList attributeArray = new ArrayList (); ArrayList queryArray = новый ArrayList ();

            int iteration = 0;

            bool hasSpecial = false ;
        nodelist = doc.SelectNodes("/Request");
        foreach (XmlNode xn in nodelist)
        {
            try
            {
                type = xn["type"].InnerText;
                id = xn["ID"].InnerText;
                attribute = xn["attribute"].InnerText;
                Debug.WriteLine("Processing Request of type: " + type + "\nWith Id number: " + id + "\nWith attribute string: " + attribute);
                for (int i = attribute.IndexOf('|'); i != -1; )
                {
                    attributeArray.Add(attribute.Substring(0, i));
                    if (attribute.Substring(0, i).Contains('\''))
                        hasSpecial = true;
                    attribute = attribute.Substring(i + 1);

                    i = attribute.IndexOf('|');
                }

// установка переменных if (type == "1" && attributeArray.Count! = 2) {s.sessionID = attributeArray [0] .ToString (); s.time = DateTime.Now; s.timer.Start (); isNotLogin = true; attributeArray.RemoveAt (0); } иначе, если (тип! = "1") {s.sessionID = attributeArray [0] .ToString (); s.time = DateTime.Now; s.timer.Start (); isNotLogin = true; attributeArray.RemoveAt (0); }

Я возвращаю структуру здесь

 public SessionStruct getSessionStruct()
    {
            return s; 
    }

Он возвращается в другой класс, например:

                        sessStruct2 = iRequest.getSessionStruct();
                        int x;
                        for(x = 0; x< session.Count; x++)
                        {
                            sessStruct = (SessionStruct)session[x];


                            if (sessStruct.sessionID == sessStruct2.sessionID)
                            {
                                Debug.WriteLine("Resetting Session Timer");
                                session.RemoveAt(x);
                                sessStruct2.timer.Stop(); //resetting timer
                                sessStruct2.timer.Start();
                                Debug.WriteLine("Session Timer Reset SUCCESSFUL");
                                session.Add((object)sessStruct2);
                                Debug.WriteLine("Added Session        "+sessStruct2.sessionID+" Successfully to sessions table");
                                guiServer.log("Added Session " + sessStruct2.sessionID + " Successfully to sessions table");
                                break;
                            }

                       }

                        if(x==session.Count)
                        {
                                session.Add(iRequest.getSessionStruct());
                                Debug.WriteLine("Added the session");
                        }

И я создал поток, который проверяет, истек ли таймер вот так

while (true)
            {
                if (session.Count > 0)
                {

                    session1 = (SessionStruct)session[0];
                    session1.timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed)

                }
            }

А вот трассировка стека:

 first chance exception of type 'System.OutOfMemoryException' occurred in mscorlib.dll

System.Transactions Critical: 0: http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/UnhandledUnhandled exceptionVNurseService.exeSystem.OutOfMemoryException, mscorlib, Version = 4.0.0.0, Culture = нейтральный, PublicKeyToken = b77a5c561934e089 Возникло исключение типа System.OutOfMemoryException. в System.MulticastDelegate.CombineImpl (следуют делегаты) в System.Timers.Timer.add_Elapsed (значение ElapsedEventHandler) в VNurseService.Server.Session.checkSessionList () в System.Threading.ThreadHelper.ThreadStart_Context.ThreadStart_Context.ThreadStart_Context.ThreadStart_Context. (состояние объекта) .Run (ExecutionContext контекст выполнения, обратный вызов ContextCallback, состояние объекта, логическое значение ignoreSyncCtx) в System.Threading.ExecutionContext.Run (ExecutionContext executionContext, ContextCallback, обратный вызов, состояние объекта) в System.Threading.ThreadHelper.ThreadStart () Тип исключения System.Outception: Возникло исключение System.OutOfMemoryException. в System.MulticastDelegate.CombineImpl (делегаты следуют) в System.Timers.Timer.add_Elapsed (значение ElapsedEventHandler) в VNurseService.Server.Session.checkSessionList () в System.Threading.ThreadHelper.ThreadStart_Context.ExreadStart_Context.ThreadStart_Context. (состояние объекта) .Run (ExecutionContext ExecutionContext, обратный вызов ContextCallback, состояние объекта, логическое значение ignoreSyncCtx) в System.Threading.ExecutionContext.Run (ExecutionContext executionContext, ContextCallback, обратный вызов, состояние объекта) в System.Threading.ThreadHelper.ThreadStart () Необработанное исключение системного типа .OutOfMemoryException 'произошло в mscorlib.dll

Я знаю, что это сбивает с толку, но мы создаем псевдо-сеансы, а идентификатор сеанса исходит из запроса, и когда запрос анализируется, он вставляет идентификатор сеанса и время, а затем запускает таймер в структуру. Затем структура возвращается в «основной» класс и затем проверяется на соответствие другим сеансам в массиве сеансов. Если он находится в arraylist, он удаляет текущую и добавляет новую структуру в конец arraylist. Затем новый поток проверяет массив массивов, чтобы узнать, не истек ли сеанс с индексом 0 в списке массивов.

Я надеюсь это имеет смысл. Если есть другая реализация или способ сделать это, пожалуйста, дайте мне знать.

Спасибо.


person Jonathan Harris    schedule 05.04.2011    source источник
comment
Код, который у вас есть, выглядит нормально, и проблем с использованием таймера, который является свойством структуры, быть не должно. Вы не показали нам, как вы подключили свое мероприятие или создали экземпляр таймера. Вы также не указали точную строку кода, в которой происходит исключение, или полную информацию об исключении, включая трассировку стека и сообщение об ошибке.   -  person Daniel Hilgarth    schedule 05.04.2011
comment
Изменяемые структуры - это ЗЛО!   -  person SLaks    schedule 05.04.2011
comment
Вы не показываете, как создается структура и как создается таймер.   -  person asawyer    schedule 05.04.2011
comment
@SLaks: Не хотите дать ссылку? (Нет, я не гуглил: p)   -  person Daniel Hilgarth    schedule 05.04.2011
comment
@Daniel: Примерно 1/3 сообщений в блоге Эрика Липперта. stackoverflow.com/questions/441309/why-are-mutable -structs-evil blogs.msdn.com/b/ericlippert/archive/2008/05/14/ blogs.msdn.com/b/ericlippert/archive/2011/03/29/   -  person SLaks    schedule 05.04.2011
comment
Я повторяю комментарий SLaks. Вы также должны подумать о равенстве - типы значений (структуры) обычно должны реализовывать равенство на основе значений, а большинство реализаций Timer этого не делают. Я думаю, вам действительно стоит пересмотреть использование структуры здесь вместо класса. Однако эти проблемы ортогональны вашей проблеме нехватки памяти.   -  person Adam Ralph    schedule 05.04.2011
comment
@SLaks: Спасибо за ссылки!   -  person Daniel Hilgarth    schedule 05.04.2011
comment
Эм ... Мне не нравится этот цикл while ... это выглядит подозрительно. while (true) - первое место, где я бы искал проблему с памятью   -  person Ryan Bennett    schedule 05.04.2011


Ответы (1)


Да, у вас может быть Timer (или любой другой тип) быть членом struct. Между прочим, вы должны настоятельно подумать о том, чтобы изменить его на class (есть ли какая-то особая причина, по которой вы сделали это struct?), Или удалите сеттеры из ваших свойств; изменяемые структуры, как здесь, обычно считаются чистым злом.

Здесь не так много того, что на самом деле говорит что-либо о вашей среде и о том, что может вызвать у вас нехватку памяти. Не могли бы вы пролить свет на то, как вы на самом деле используете struct?

Редактировать после вопроса Редактировать

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

person Adam Robinson    schedule 05.04.2011
comment
это сработало, спасибо большое. Однако теперь я получаю аргумент вне диапазона исключений, когда мне не должно быть? Я не знаю, могу ли я задать здесь еще один вопрос, но, может быть, я - person Jonathan Harris; 06.04.2011
comment
@Jonathan: Тебе, наверное, стоит открыть новый вопрос. Не забудьте отметить этот ответ как принятый, если он отвечает на ваш вопрос. - person Adam Robinson; 06.04.2011