Всем здравствуйте,
Я задавал аналогичный вопрос на stackoverflow, но, видимо, там мне помочь не в силах. Испытаю удачу здесь.
Пишу плагин для CAD/CAE-системы. Название ее писать не буду, скажу лишь, что нынешние владельцы - немцы, но писали ее индусы, со всеми вытекающими... Проблем за год работы с этой системой и ее API - было МОРЕ, но нынешняя обезоружила и надругалась надо мной.
Плагин пишу на C# .NET 4.0, использую VS 2010 sp1. Казалось бы, победа была близка, но тестирование показало, что после второго запуска плагина (т.е. уже когда плагин второй раз отработает), - система зависает и появляется окошко "Сервер занят...". Окошко это не убрать, система никак не реагирует, приходится убивать процесс.
Стал дебажить. Выяснил, что код кидает AccessViolationException.
Важно: исключение возникает при втором запуске плагина! При первом запуске - все проходит отлично! Приведу пример кода:
public class TestClass : IDisposable
{
private Session theSession;
private UI theUI = UI.GetUI();
private BlockDialog theDialog;
...
public TestClass()
{
theSession = Session.GetSession();
theDialog = theUI.CreateDialog(theDlxFileName); // исключение возникает в этой строке!
theDialog.AddApplyHandler(ApplyCb);
theDialog.AddOkHandler(OkCb);
theDialog.AddUpdateHandler(UpdateCb);
theDialog.AddInitializeHandler(InitializeCb);
theDialog.AddDialogShownHandler(DialogShownCb);
}
public DialogResponse Show()
{
theDialog.Show();
...
}
public void Dispose()
{
...
theDialog.Dispose();
...
}
public SomeOtherFunction(...)
{
...
theSession...
...
}
...
}
Как видно, исключение возникает при попытке создать диалоговое окно. Еще раз обращу внимание, что мне приходится использовать кривое API для создания плагина и Session, UI, BlockDialog - это не мои классы. Чуть расскажу об этих классах: Session - это основной класс, через него происходит вся работа с тем, что предоставляет CAE-система. Через UI происходит вся работа с... интерфейсом пользователя, это логично. Конструкторов этих классов (как, впрочем, и почти всех классов в предоставляемом API) - не существует. Подозреваю, что в них реализован сигнлтон, что, в принципе, тоже логично. И, чтобы получить доступ к текущему "сеансу" программы и ГУИ необходимо использовать конструкции вида:
UI theUI = UI.GetUI();
...
theSession = Session.GetSession();
Возвращаемся к проблеме. Как оказалось, исключение возникает не при создании диалога, а при получении экземпляра Session. То есть, в этой строке:
theSession = Session.GetSession();
Как видно из первого листинга, я не использую theSession в конструкторе, и первое что приходит в голову - убрать ее от греха подальше. Однако, эта переменная нужна мне в будущем.
Стал рыть глубже. Выяснил, кто именно кидает исключение. Оказалось, проперти ActiveSketch. Что странно, при первом запуске, после получения экземпляра сеанса, theSession.ActiveSketch == null, но при втором запуске плагина возникает исключение...
Что забавно, ни до, ни после, -
никогда! - я не использую этот самый ActiveSketch...
Видимо, он обиделся, и решил попортить мне жизнь.Далее еще интереснее... В то время, пока я нахожусь в дебаге и в шоке, theSession.ActiveSketch успевает стать равным null. Как результат, если продолжить выполнение плагина, то он выполнится без проблем и CAE-система не зависнет.
Но далее еще интереснее... После второго (теперь успешного) выполнения плагина, я могу спокойно убрать все брейкпоинты и вновь запустить плагин. Что же в результате? А в результате - плагин спокойно и без проблем отрабатывает третий, четвертый, пятые разы... И система при этом не зависает.
Что делать? Как быть?