10. Начинаем шелкать чекбоксы — где то на 7-8 через 3 секунды происходит StackOveflow — what's the heck. При 3-4-х нажтых работает отлично — замерял час.
Вопрос 1: что за фигня и как бороться?
Вопрос 2: интересно как генерится StackOveflow — как он понимает что ето стак оверфло а не рекурсия или повторные действия?
Здравствуйте, <Аноним>, Вы писали:
А>Вопрос 1: что за фигня и как бороться?
Приведи полный проект, который воспроизводит проблему. Скорее всего, ты накосячил чего-то в коде.
А>Вопрос 2: интересно как генерится StackOveflow — как он понимает что ето стак оверфло а не рекурсия или повторные действия?
Очень просто. StackOverflow генерится тогда, когда переполняется стек. В частности, в результате рекурсии. Без неё получить StackOverflow малореально. Повторные вызовы не должны приводить к StackOverflow, т.к. они не используют стек.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Косячишь ты, я пробую не то ПОаккуратнее там со словами, развелось тут вас — знатоков. И вообше тебе на будушее сознание обственной непрогешимости, до хорошего не доводит Давайте посмотрим — звучит гораздо лучше, не правда ли?
Код нельзя аs we use custom eabs builds. Я нашел место — Conneciton.Open() — стак действительно длинный, но состоит внимание из повторных вызовов.
Кстати, с чего ты взял, что повторные вызовы не генерят стек??? На моём примере четко видно обратное. Похоже, стек генерится в том числе и из неисполненных нерекурсивных вызовов, что при использовании нескольких потоков является очень вероятным. Стек дать могу, смотри внизу.
> Microsoft.Practices.EnterpriseLibrary.Data.dll!Microsoft.Practices.EnterpriseLibrary.Data.Database.OpenConnection() Line 1206 + 0xb bytes C#
Microsoft.Practices.EnterpriseLibrary.Data.dll!Microsoft.Practices.EnterpriseLibrary.Data.Database.ExecuteScalar(System.Data.Common.DbCommand command = {System.Data.SqlClient.SqlCommand}) Line 588 + 0x8 bytes C#
Microsoft.Practices.EnterpriseLibrary.Data.dll!Microsoft.Practices.EnterpriseLibrary.Data.Database.ExecuteScalar(string storedProcedureName = "sp_feed", object[] parameterValues = {Dimensions:[3]}) Line 631 + 0xb bytes C#
WindowsApplication1.exe!WindowsApplication1.Form1.Feed(object sender = {Interval = 100}, System.EventArgs e = {System.EventArgs}) Line 60 + 0x14 bytes C#
повтор около 100 раз, не считал.
Сойственно ошибетс:
An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
Откуда берется такая уверенность в собствнной непогршимости?
On provotsiruet generaciju stack'a, ja pravil'no ponimau, which in turn throws stack overflow? Ja pravil'no ponimau? Prosto etot komponent dolgen imet' UI — ssdealt' na delegatah budet rabotat'?
Здравствуйте, <Аноним>, Вы писали:
А>On provotsiruet generaciju stack'a, ja pravil'no ponimau, which in turn throws stack overflow? Ja pravil'no ponimau? Prosto etot komponent dolgen imet' UI — ssdealt' na delegatah budet rabotat'?
Здравствуйте, <Аноним>, Вы писали:
А>On provotsiruet generaciju stack'a, ja pravil'no ponimau, which in turn throws stack overflow? Ja pravil'no ponimau?
Ситуация примерно следующая:
Винда кладет в очередь оконных сообщений сообщение WM_TIMER. Цикл обработки сообщений натыкаясь на это сообщение запускает твой обработчик. Этот обработчик работает какое-то время. Если это время превышает интервал таймера, то за время его работы винда в очередь оконных сообщений кладет очередной WM_TIMER. Если после этого ты где-то в своем обработчике вызовешь Application.DoEvent, то начнется "обработка" сообщений, поступивших в очередь. В том числе в этой очереди лежит и WM_TIMER, встретив который приложение запускает твой обработчик.
То есть получаем ситуацию, когда обработчик запускается 2-й, 3-й, ..., n-ый раз до завершения 1-ого, 2-го и (n-1)-ого вызова. Каждый вызов метода "занимает" определенное место на стеке. При достижении достаточно большого n размера стэка уже не хватает и мы получаем переполнение стэка.
А>Prosto etot komponent dolgen imet' UI — ssdealt' na delegatah budet rabotat'?
Если ты имеешь в виду асинхронные длегаты, то да, будет работать.
Еще как вариант — отключать таймер(ы) в начале работы обработчика и включать по завершении.
Здравствуйте, DmitryMS, Вы писали:
DMS>will that help, you reckon?
Думаешь не поможет?! Мне вот, например, думаю, как и многим, не интересно читать вопросы людей не удосуживающих потратить немного сил для транслитерации.
Здравствуйте, DmitryMS, Вы писали: DMS>Откуда берется такая уверенность в собствнной непогршимости?
У меня нет уверенности в собственной непогрешимости. Просто я знаю, что такое Stack Overflow. И знаю, как работает компьютер.
Возвращаясь к теме:
Вся проблема — в идиотской структуре оконных таймеров и их взаимосвязи с циклом выборки оконных сообщений.
Грубо говоря, метод DoEvents выполняет неявную рекурсию, если он вызван внутри обработчика оконного события (в том числе и события таймера).
В результате получается такая штука: срабатывает таймерное событие, до возврата из его обработчика ты вызываешь DoEvents, который в свою очередь находит обработчик таймерного события и заново его запускает — и всё это до возврата из первого обработчика. Получается неявная рекурсия, вызванная именно твоим косяком — вызовом DoEvents из обработчика таймерного события.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: ADO.NET v2 & StackOveflow
От:
Аноним
Дата:
15.01.07 12:31
Оценка:
Не используй WinForms Timer. Он базируется на оконных событиях, которые дергает DoEvents.