Управление COM-объектом в C # - PullRequest
2 голосов
/ 24 марта 2009

У меня есть ATL COM exe, который я звоню из C #. Я импортирую ссылку в C #, и все работает нормально, исполняется exe, и я могу вызывать функции на нем. Теперь я создаю несколько таких COM-объектов. Изредка один из них будет висеть. Освобождение объекта COM ничего не делает, так как он все еще работает. Я не могу убить процесс, потому что тогда я теряю все свои другие объекты, которые ведут себя очень хорошо. Таким образом,

  1. есть ли способ по-настоящему убить только одного?
  2. есть ли способ запустить один exe для каждого запрошенного com-объекта?
  3. если мой клиент неожиданно завершает работу, COM exe никогда не очищается. Есть ли способ это исправить?

В идеале я мог бы запустить по одному COM-файлу для каждого экземпляра объекта и иметь возможность Process.Kill (). Является ли один из этих вариантов? Класс, который я использую для создания объекта ниже, RandomID () (искусственно) занимает очень много времени, чтобы вернуться в этом случае. Кроме того, если есть способ сделать это на другом языке, я хотел бы попробовать это тоже. Спасибо.

public class MyComObject:IDisposable
{
    private bool disposed = false;
    MyMath test;

    public MyComObject()
    {
        test = new MyMath();
    }

    public double GetRandomID()
    {
        if (test != null)
            return test.RandomID();
        else
            return -1;
    }

    public void Dispose()
    {
        Dispose(true);

        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (test != null)
                Marshal.ReleaseComObject(test);

            disposing = true;
        }
    }
}

РЕДАКТИРОВАТЬ: Похоже, что если я могу установить это "Одноразовое использование", все будет работать, как я хотел Однако я не могу найти, где установить эту опцию в VS 2008

РЕДАКТИРОВАТЬ: нашел ответ в группах Google

class CMathServerModule : public CAtlExeModuleT< CMathServerModule >
   {

    public :
   DECLARE_LIBID(LIBID_MathServerLib)
   DECLARE_REGISTRY_APPID_RESOURCEID(IDR_MATHSERVER, "{2FA977F0-050C-4010-A09F-4FE6D75F3024}")
   HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) 
   throw() 
    { 
        dwFlags = ((dwFlags & ~(REGCLS_MULTIPLEUSE | REGCLS_MULTI_SEPARATE )) | 
                REGCLS_SINGLEUSE); 
        return CAtlExeModuleT<CMathServerModule>::RegisterClassObjects(dwClsContext, dwFlags); 
    } 
   };

Ответы [ 3 ]

2 голосов
/ 24 марта 2009

Что происходит, когда объект висит? то есть откуда ты знаешь, что оно зависло?

Существует множество причин, по которым он мог зависнуть, но одна из них заключается в том, что поток где-то в системе инициализировал COM, но не перекачивает сообщения Windows.

Контролируете ли вы исходный код exe-сервера COM? Это может быть намного проще, чем DLL-сервер, так что вы можете загрузить его в процессе, где ни одна из этих проблем не существует.

Обновление:

Учитывая информацию в комментариях, вы используете COM exe-remoting для решения проблемы 32/64-битного thunking.

Мой опыт работы с серверами COM exe был не чем иным, как ужасным. COM DLL - это действительно простые вещи, COM exe - это очень сложные и ненадежные вещи. Они работают нормально - просто - в некоторых интерактивных сценариях с графическим интерфейсом.

Но вам, вероятно, было бы лучше использовать собственный механизм IPC, как ни странно. Это на самом деле не так сложно. Предположим, 64.exe создает сокет прослушивания, а также поддерживает дескриптор процесса 32.exe, создавая его по требованию. Он может создавать столько, сколько ему угодно, и убивать их по прихоти. Когда запускается 32.exe, он подключается к сокету и читает на нем - вот как это работает. 64.exe отправляет инструкции через принятое сокет-соединение, которое сохраняется вместе с соответствующим дескриптором процесса.

Прелесть этого в том, что если 64.exe внезапно умирает, 32.exe получит ошибку при чтении сокета и умрет также.

Формат того, что вы отправляете в сокет, может быть очень простым. Подсчитанный буфер идеален (отправьте длину, после которой следует столько байтов данных).

1 голос
/ 24 марта 2009

Я не знаю, является ли это ответом, но код в вашем методе Dispose устанавливает параметр dispose в true и не удаляется Это позволяет несколько вызовов ReleaseComObject.

Я бы установил значение true и посмотрел, есть ли у вас такая же проблема.

0 голосов
/ 27 марта 2009

Я разработал некоторые службы, экспортирующие COM-интерфейс, и у меня нет проблем, это выполняется в пуле серверов.
Мое предложение состоит в том, чтобы попробовать контролировать ваше приложение с помощью WinDbg, скомпилировать код, включающий отладочную информацию, и установить файлы pdb вместе.

...