Хорошо, первое, что я должен сказать об этом коде, это WTF ?! Вам нужно немного изучить, как работают сообщения Windows. Я немного расскажу здесь, но вам действительно нужно понять это, прежде чем погрузиться в игру и попытаться сделать сумасшедшие вещи, подобные тому, что я вижу здесь.
- Когда создается окно, все «действия» для этого окна доставляются через сообщения Windows. Когда вы звоните «Обновить», «Кликаете» или что-то в этом роде, это сообщение Windows.
- Эти сообщения отправляются из «насоса сообщений», который представляет собой просто цикл, который вызывает API-интерфейсы PeekMessage, GetMEsssage, TranslateMessage и DispatchMessage.
- Application.Run делает это в управляемом коде.
- Сообщения Windows для формы должны доставляться в том же контексте потока, что и окно, которое было создано. Это означает, что насос также должен быть на одной и той же резьбе. Вот почему существует Control.Invoke.
- Насос в одном потоке не будет даже видеть сообщения в окне в другом потоке
Так что, безусловно, есть некоторые проблемы с тем, что вы делаете. Я не уверен, что представляет собой «общая картина» того, чего вы пытаетесь достичь, и как вы могли заметить эту ошибку, но этот код говорит мне, что у вас есть некоторые фундаментальные проблемы в вашей архитектуре.
Но как насчет этой утечки, вы думаете, вы все равно нашли? Ну, нет утечки. Вы не понимаете CF (и управляемое) управление памятью. Опять же, исследование рекомендуется, но MSDN имеет действительно хорошую веб-трансляцию, которая хорошо освещает ее .
Суть этого сценария в том, что вы создали несколько объектов в отдельных потоках. Эти потоки создают кучу вещей, некоторые из которых IDisposable, некоторые нет. Когда нить срывается, эти предметы больше не имеют корней, поэтому доступны для сбора. Когда вызывается Collect, GC обходит все корни и отмечает каждый объект, имеющий корень (метку). Те, которые этого не делают, «освобождаются» (развертки). Область в куче GC, в которой они находились, просто больше не помечена как используемая - подробности см. В веб-трансляции. Если элемент реализовал IDisposabe, то получает новый корень , поэтому финализатор все еще может существовать и запускать в следующем цикле GC . И, наконец, завершает поток финализатора (недетерминированно).
Ваш код не учитывает это поведение. Вы не запускали Collect дважды. Вы не ожидали финализаторы после вызова Collect (и простого вызова WaitForPendingFinalizers может быть недостаточно). Поскольку сами ваши потоки не помечены как фоновые потоки, кто знает, какова их позиция в их жизненном цикле и состояние использования GC.
Итак, когда мы действительно приступаем к этому, возникает вопрос: что именно вы пытаетесь решить? Вы работаете в среде управляемой памяти. Если вы не видите OOM, вы почти всегда не должны беспокоиться об уровнях памяти - в этом весь смысл наличия GC. Не пытайтесь строить замысловатые учебные занятия Уолдо и попросите нас найти утечку.
Если у вас действительно есть проблема, то сначала убедитесь, что дизайн вашего приложения соответствует тому, как должны быть написаны приложения для Windows, а затем используйте инструменты, такие как RPM , чтобы определить, какие корни хранятся памяти и исправления созданных вами утечек (да, утечки все еще могут происходить и происходят в управляемом коде). Конечно, вы всегда можете задать разумные вопросы о проблеме real world и здесь.
EDIT
Microsoft, похоже, удалила содержимое веб-трансляции, о котором я упоминал выше. Надеюсь, они смогут найти его и опубликовать повторно, но в то же время (и если они его никогда не найдут) у меня по крайней мере есть PowerPoint, который я использовал для первоначального выступления в MEDC, и он доступен в моем блоге .