Сборщик мусора, запускающий слишком рано (возможно), в то же время выполняя код низкого уровня c ++ - PullRequest
2 голосов
/ 04 апреля 2019

Я получаю странный прерывистый сбой в моем коде c ++, потому что мой управляемый класс c ++ удаляется GarbageCollector (возможно).Я вижу деструктор, вызываемый до завершения DoingSomeLowLevelStuff.Добавление пустого вызова в конце функции решает проблему, но я не уверен, почему GC начинает работать вообще, поскольку «WManagedClass c» все еще находится в области действия.

DoingSomeLowLevelStuff функция занимает немного времени, чтобызавершить (несколько секунд), поскольку он выполняет несколько сетевых вызовов.

C #:

void func()
{
   WManagedClass c = new WManagedClass();

   DataSet x = c->DoingSomeLowLevelStuff(); //intermittent crash in there

   //do some stuff with x here

   //adding this line fixes it

   c->DoNothing(); //empty call in WManagedClass
}

На самом деле я должен был указать, что func получает вызовы из фоновых рабочих потоков.

BackgroundWorker bg_C = new BackgroundWorker(); 
bg_C.DoWork += (sender, args) => //called to do work in background 
{ 
}; 
bg_C.RunWorkerCompleted += (sender, args) => 
{ 
func(); 
}; 
bg_C.RunWorkerAsync();

А вот управляемый c ++, включая DoingSOmeLowLevelStuff

public ref class WManagedClass
{
protected :

    !WManagedClass()
    {
        if (pLowLevelClass)
            delete pLowLevelClass;
        pLowLevelClass = NULL;
    }

public :

    CLowLevelClass* pLowLevelClass;
    WManagedClass()
    {
        WSADATA wsaData;
        short wVersionRequested;

        wVersionRequested = MAKEWORD(2, 0);
        if (WSAStartup(wVersionRequested, &wsaData) != 0)
        {
            fprintf(stderr, "WSAStartup failed.");
            return;
        }

        pLowLevelClass = new CLowLevelClass();
    }
    ~WManagedClass()
    {
        this->!WManagedClass();
    }

void DoNothing()
{
}
    DataSet^ DoingSomeLowLevelStuff()
    { 
        CDpDataSet* pDS = pLowLevelClass->DoingSomeLowLevelStuff();
        DataSet^ ds = nullptr;
        if (pDS) 
        {
            pDS->Name = "name";
            ds = ConvertDataSet(pDS);
            delete pDS;
        }
        return ds;
    }
...