COM-объект, который был отделен от базового RCW, не может быть использован - PullRequest
2 голосов
/ 21 сентября 2011

Я пишу XML AJAX Service с OPC-сервером. Служба XML AJAX на основе этого примера. И я сделал свой сервис с одним атрибутом:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

И следующим шагом я создаю деструктор класса:

~BoilerService()
{
    try
    {
        ReadTimer.Dispose();
        group.ReadCompleted -= new ReadCompleteEventHandler(group_ReadCompleted);
        group.Remove(true);
        server.Disconnect();
    }
    catch (Exception e)
    {
        System.IO.StreamWriter sw = new System.IO.StreamWriter("log.txt", true);
        sw.WriteLine(DateTime.Now.ToString() +e.Message+ " "+ e.Source+" "+e.StackTrace +  " destructor called.");
        sw.Close();
        sw.Dispose();
    }
}

Но когда я перестраиваю свое решение в VS (файлы заменяются в пути к приложению), я получаю окно ошибки необработанного исключения wp3.exe (Windows 7). И в журнале событий Windows я вижу следующий текст:

Exception: System.Runtime.InteropServices.InvalidComObjectException

Message: COM object that has been separated from its underlying RCW cannot be used.

StackTrace:    at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, Boolean& pfNeedsRelease)
   at OPC.Data.Interface.IOPCServer.RemoveGroup(Int32 hServerGroup, Boolean bForce)
   at OPC.Data.OpcGroup.Remove(Boolean bForce)
   at OPC.Data.OpcGroup.Finalize()

Что я сделал не так?


И VS 2010 дают предупреждения: 1. «System.Runtime.InteropServices.UCOMIEnumString» устарел: «Вместо этого используйте System.Runtime.InteropServices.ComTypes.IEnumString. http://go.microsoft.com/fwlink/?linkid=14202'. 2. «System.Runtime.InteropServices.UCOMIConnectionPointContainer» устарел: «Вместо этого используйте System.Runtime.InteropServices.ComTypes.IConnectionPointContainer. http://go.microsoft.com/fwlink/?linkid=14202'

Может ли эта ошибка появиться из-за этого предупреждения?

1 Ответ

5 голосов
/ 21 сентября 2011

Согласно документации MSDN

Финализаторы двух объектов не гарантированно работают в каком-либо определенном порядке, даже если один объект ссылается на другой. То есть, если у Объекта A есть ссылка на Объект B, и оба имеют финализаторы, Объект B, возможно, уже был завершен, когда запускается финализатор Объекта.

Это означает, что если group можно собирать одновременно с вашим экземпляром OpcGroup (что представляется весьма вероятным), вполне возможно, что group уже завершен, что может быть причиной вашей неудачи.

Похоже, вы пришли из C ++ фона, и в этом случае вы должны знать, что финализаторы работают по-другому в C # - это очень редко, когда вам когда-либо нужно реализовывать финализатор. Я бы порекомендовал вместо того, чтобы выполнить эту очистку в финализаторе, вместо этого вы внедрили IDisposable и выполняете эту работу, когда объект удаляется.

Также вам обычно не нужно отсоединять обработчики событий (если только событие не может быть запущено и может вызвать исключение после удаления объекта). Этот вид очистки обрабатывается для вас.

...