|
|
Регистрация Восстановить пароль |
Повторная активизация e-mail |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
|
Опции темы | Поиск в этой теме |
29.03.2018, 03:13 | #1 |
Спокойный псих
Участник клуба
Регистрация: 19.03.2013
Сообщений: 1,538
|
Ошибка с повреждением памяти процесса (C#)
Здравствуйте. Я на форуме уже спрашивал по поводу этой ошибки, но не обнаружил тему в списке созданных мною.
Скриншот ошибки прикрепил. Из-за чего могут вообще появляться такие ошибки ? Помимо варианта криворукости автора; это я и пытаюсь исправлять. В гугле у всех по разному, но в основном у всех "проблемы с массивом". Я же для теста исключил содержание объектов в массивах, но как водится, проблема не исчезла. Задача программы - обеспечивать хаотичное (не синхронизированное) поведение объектов (игра по типу Tower Defence - перемещение, наведение, стрельба, ну и так далее, проблемы теперь на стрельбе). По большому счёту, программа падает просто потому что потоки не синхронизированы, ну это как я понял. Но мне и не нужно их синхронизировать, так как у каждого объекта своя цель, и выполнение не должно зависеть от поведения соседних объектов. И всё же, я решил забавы ради кинуть неуправляемую (lock) синхронизацию на главный поток процесса (интерфейс, окно программы), и получил завершение программы с кодом 0x4000001f в отладчике. То есть программа теперь просто падает, без возможности узреть место-время-причину ошибки. То самое чувство, когда осознаёшь, что ошибка не в коде, хотя технически это всё равно не так. Пока что ввёл динамическое ограничение: чем больше выстрелов "в полёте" - тем дольше задержка перед следующим выстрелом (для всех стреляющих). И пока вроде даже держится. P. S. Здесь уже не важно, как именно я реализую много-поточность, любая реализация с таким подходом должна и будет падать, видите ли, "система на что то там не рассчитана". Ну и я дурак. Может что то не так понял ? Что то я приуныл, пойду посплю. Что вы можете подсказать ? Эта тема больше подходит для форума "свободное общение", но тематика всё же решает
Подпись ? Не, не слышал ...
|
29.03.2018, 07:32 | #2 |
Старожил
Регистрация: 15.02.2010
Сообщений: 15,709
|
Скорее всего вы пытаетесь нарисовать что-то, что уже уничтожилось в соседнем потоке. Обычно не синхронизируют логику, цели потоков и т.д. Синхронизируют общие ресурсы, например, список объектов для отрисовки.
|
29.03.2018, 08:02 | #3 | |||
Старожил
Регистрация: 22.05.2007
Сообщений: 9,065
|
Цитата:
Смысл синхронизации в том, чтобы не ломать общие ресурсы и получать правильные данные. Поведение объектов может быть хоть хаотичным, хоть одинаковым, вообще никакого отношения к синхронизации не имеет. Если они где-то хранятся в общей коллекции, то нужно эту коллекцию делать thread-safety. Цитата:
Цитата:
Читать про особенности многопоточной разработки. |
|||
29.03.2018, 09:40 | #4 | |||
Спокойный псих
Участник клуба
Регистрация: 19.03.2013
Сообщений: 1,538
|
Цитата:
Цитата:
Но при таком поведении, ресурсы нужно же освобождать, чем я и занимаюсь в Dispose/Finalize (innerImg.Dispose();). Я конечно же могу возложить болта на регулярно-хаотичное выделение памяти, и пускай этим занимается GC. Но я не очень уверен в том, что это поможет ... Ресурсы то "разбросаны", а моя общая проблема проявляется при постоянно-быстрой работе объектов. И действительно, это происходит именно в этом моменте: Но в данных отладки при падении все данные объекта вроде как даже целые. Цитата:
Код:
Что тут может быть не так ?
Подпись ? Не, не слышал ...
Последний раз редактировалось OmegaBerkut; 29.03.2018 в 10:05. |
|||
29.03.2018, 10:35 | #5 |
Старожил
Регистрация: 22.05.2007
Сообщений: 9,065
|
Не так тут архитектура сделана. Не те объекты не тем занимаются и всё это в многопоточности. Не знаю откуда взялось стремление каждый выстрел выделить в отдельный поток, но подозреваю, что там в целом подход неправильный и игра работает не так, как нужно (одному потоку досталось больше процессорного времени и снаряд дальше улетел, другой дольше спал и снаряд завис на месте).
Для начала хотя бы однопоточный вариант нужно сделать, чтобы всё правильно работало, а потом уже пытаться распараллелить, если вообще это нужно будет. |
29.03.2018, 10:41 | #6 |
Спокойный псих
Участник клуба
Регистрация: 19.03.2013
Сообщений: 1,538
|
Вариант с неравномерным разделением процессорного времени получается менее тормознутым. Чем больше выстрелов будет обрабатывать один поток - тем дольше будет работать собственно поток.
При условных 30 маленьких потоках неравномерность разделения процессорного времени получается незначительна, и общая скорость выполнения остаётся визуально в пределах нормы. Однопоточный вариант работает нормально, но как я и сказал, когда я начал напихивать в него больше выстрелов - время прохождения маршрута растёт прямо пропорционально количеству выстрелов. Отсюда и разделение на потоки.
Подпись ? Не, не слышал ...
|
29.03.2018, 12:15 | #7 |
Старожил
Регистрация: 22.05.2007
Сообщений: 9,065
|
На сколько я знаю, в играх делается так:
засекается время с предыдущего отображения сцены. пересчитываются координаты снарядов с учётом этой дельты. допустим, у нас снаряд летит 10 метров/с, у нас прошла 1 секунда, смещаем снаряд на 10 метров. прорисовываем изменённую сцену. в процессе обработки сцены соответственно можно параллельно пересчитать координаты всех выстрелов и всё, что можно распараллелить. иначе получится, что на мощных компах слишком быстро играется, на слабых - черепашья скорость и вообще баланс игры не выстроишь никак. В общем, гуглим "игровой цикл" и делаем как у других. Это с ошибкой из первого сообщения никак не связано, но текущую реализацию я бы не допиливал, ибо она утопична. |
29.03.2018, 12:27 | #8 | |
Спокойный псих
Участник клуба
Регистрация: 19.03.2013
Сообщений: 1,538
|
Цитата:
Что касается конкретно текущей реализации - описанная вами ситуация будет проявляться при больших количествах объектов, что как ни странно, нормальное явление для любой серьёзной и не очень игры. Если у каждого снаряда своя скорость движения, т. е. своё время задержки потока, то при "нормальных" условиях всё же нормально должно быть ... Хм ... Как то абстрактно выглядит. Чего утопичного то (?) Возвращаясь к своей ошибке ... Я её раньше решал перепиливанием ресурсов. Сейчас это не спасает. Убрал код, отвечающий за принудительное освобождение ресурсов (повесил на GC.Collect();), убрал "самоизвлечение" объекта из коллекции, так же дописал код, отвечающий за удаление ссылок из массива в отдельном игровом потоке. Проблема не исчезла. Из чего можно сделать преинтереснейший вывод, что некто истребляет данные объекта до того, как поток объекта завершит работу. Кстати, у Graphics в месте падения оказывается куча Exceptions внутри. Думал, что проблема находится где то в районе попыток самоуничтожения потока (предполагалось, что поток сам выпилит все следы существования объекта-носителя), но - я перепилил на флаги состояния + уничтожение из-вне потока и объекта, и как всегда, проблема осталась во всей красе. Прикол этой ошибки в том, что при её возникновении программа вообще теряет возможность выполнять что либо и где либо. Это исключение можно поймать в обработку только со специальными ухищрениями (правки App.config), когда я научил программу обрабатывать именно это исключение - программа вешалась целиком и полностью (в этом и отражается название темы). Дальше про потоки. Так же, метод Thread.Abort() всё равно приходится вызывать, даже после того, как поток вышел за пределы функции - он всё ещё IsAlive && ThreadState.Running && !ThreadState.Stopped && !ThreadState.Suspended короче, независимо от настроения Аллаха, положения звёзд планет астероидов и Луны, поток никак и никогда не завершается без аборта оного, и если IsBackgound==false - вся программа не сможет самостоятельно и честно закрыться. Но во избежание проблем с отладкой всё равно приходится вешать флаги, и ждать завершения выполнения функции, а только после пускать аборт. Что-что, а на плюсиках с потоками было хоть и муторнее, но всё же проблем таких не было (я и рисовал в MFC, правда без нагрузочных тестов), а тут от плевка в сторону Graphics по велению того самого некто вешается и сыпется всё.
Подпись ? Не, не слышал ...
|
|
29.03.2018, 12:50 | #9 | |||||
Старожил
Регистрация: 22.05.2007
Сообщений: 9,065
|
Цитата:
Цитата:
Цитата:
Допустим у нас 50 выстрелов. Мы для них создаём 50 неуправляемых потоков. На каждый поток ОС тратит ресурсы и определяет какому из них сейчас дать время поработать. Вместо этого я предлагаю написать простой цикл foreach или Parallel.ForEach и в нём посчитать новые координаты снарядов. Никаких переключений контекстов и т.п. И быстрее и правильнее. Цитата:
Цитата:
Есть проверенный временем подход с игровым циклом, не нужно ничего усложнять и изобретать велосипед. В Windows оконные приложения подобным образом работают, так же цикл и т.д. и т.п. |
|||||
29.03.2018, 13:08 | #10 | |
Спокойный псих
Участник клуба
Регистрация: 19.03.2013
Сообщений: 1,538
|
Цитата:
Зато я смог сделать, что бы при выпадении этого исключения программа элегантно вызывала GetCurrentProcess().Kill().
Подпись ? Не, не слышал ...
|
|
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Поиск в памяти процесса | Mr_ViK | Общие вопросы Delphi | 5 | 27.08.2012 21:38 |
Редактирование памяти процесса | Dima DDM | Общие вопросы Delphi | 0 | 25.12.2010 16:54 |
Размер памяти процесса | ZaRDaK | Общие вопросы Delphi | 5 | 25.09.2010 23:48 |
Редактирование памяти процесса | Air | Win Api | 6 | 16.02.2008 20:15 |