Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Неожиданая остановка потока (Finished == true)

991
31 августа 2009 года
Zenhipster
157 / / 14.01.2005
Проект написан с использованием CodeGear C++ Builder 2009.

Есть поток:
Код:
void __fastcall TCvsConnection::TRealCamDataProvider::Execute()
{
    for(; !Terminated; )
    {
        pCvsConnection->pLockStructures->Acquire();
        try {
            GetData();
            DeliverData();
        }
        __finally
        {
            pCvsConnection->pLockStructures->Release();
                  };
        Sleep(msec >> 1);
    };
}


, и некоторая функция, которая шарит данные с потоком.
При входе в критическую секцию поток останавливается (Finished == true):

Код:
void __fastcall TCvsConnection::UnRegisterCvsCameraComponent(TCvsCamera *CvsCamera)
{
         // pRealCamDataProvider->Finished == false
    pLockStructures->Acquire();
         // pRealCamDataProvider->Finished == true
    try {
        if(CvsCamera)
        {
            if(CvsCamera->CvsConnection)
                CvsCamera->CvsConnection = NULL;

            int i;
            if((i = pRealCamDataProvider->pCvsCameraComponents->IndexOf(CvsCamera)) != -1)
            {
                if(--FCamRefCount == 0)
                {
                    pRealCamDataProvider->Terminate();
                    pRealCamDataProvider->WaitFor();
                };
                pRealCamDataProvider->pCvsCameraComponents->Delete(i);
                pRealCamDataProvider->DeleteServerCamera(
                    CvsCamera->Cam - FirstCam
                );

                if(FCamRefCount == 0)
                {
                    delete pRealCamDataProvider;
                    pRealCamDataProvider = NULL;
                };
            };
        };
    }
    __finally {
        pLockStructures->Release();
    };
}


Такое происходит через раз (случайно). При этом ни pRealCamDataProvider->Terminate(); , ни delete pRealCamDataProvider; , в приведенной функции нигде не вызываются.
В чем причина?
38K
31 августа 2009 года
Tsukasa-mixer
7 / / 30.04.2008
Сам с подобной проблемой в Rad Studio 2009 столкнулся - когда поток по неизвестной причине завершается (эт правда в Делфи)
 
Код:
procedure TEventWaitThread.Execute;
begin
  while True do
  begin
    if WaitForSingleObject(CommandEvent, INFINITE) <> WAIT_OBJECT_0 then Exit;
    PostMessage(face.Handle, WM_CommandArrived, 0, 0);
  end;
end;

По неизвестной причине код стал самостоятельно завершатся без причинно.
991
01 сентября 2009 года
Zenhipster
157 / / 14.01.2005
вот еще пару функций:

если закоментировать строчку '((TCvsCamera*)(lste->GetCurrent()))->PaintFrame();',
то все работает.

 
Код:
void __fastcall TCvsConnection::TRealCamDataProvider::DeliverData()
{
    TListEnumerator *lste = pCvsCameraComponents->GetEnumerator();

    while(lste->MoveNext())
    {
            ((TCvsCamera*)(lste->GetCurrent()))->PaintFrame();
    };
}


Код:
void __fastcall TCvsCamera::PaintFrame()
{
    if(FCvsConnection && FActive && Parent)
    {
        int icam = FCam - FCvsConnection->FirstCam;
        byte *pJpeg = FCvsConnection->pRealCamDataProvider->pFrames[icam];
    #pragma warn -8098
        if(pJpeg && (*(DWORD*)(pJpeg+6) != 'FIFJ'))
            pJpeg = FCvsConnection->GetPicNoSignal();
    #pragma warn .8098
        int w, h, channels;
        GetJpegWH(pJpeg, &w, &h, &channels);
        char *buf = new char[w * h * channels];
        DecompFromJPEGBuf(
            pJpeg,
            w * h * channels,
            w,
            h,
            channels,
            buf
        );

        Canvas->Lock();
        HDC hdcDst = Canvas->Handle;
        HDC hdcSrc = CreateCompatibleDC(hdcDst);
        HBITMAP hbmSrc = CreateCompatibleBitmap(hdcDst,
            Width,
            Height
        );
        SelectObject(hdcSrc, hbmSrc);

        HDC hdcTitle = CreateCompatibleDC(hdcDst);
        HBITMAP hbmTitle = CreateCompatibleBitmap(hdcDst,
            Width,
            24
        );

        TCanvas *cnvSrc = new TCanvas();
        cnvSrc->Handle = hdcSrc;
        //
        BITMAPINFO bi;
        bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
        bi.bmiHeader.biWidth = w;
        // это баг микрософта, высота должна быть отрицательной
        bi.bmiHeader.biHeight = -h;
        bi.bmiHeader.biPlanes = 1;
        bi.bmiHeader.biBitCount = 8 * channels;
        bi.bmiHeader.biCompression = BI_RGB;
        bi.bmiHeader.biSizeImage = w * h * channels;
        bi.bmiHeader.biClrUsed = 0;
        bi.bmiHeader.biClrImportant = 0;

        // масштабируем Jpeg на hdcSrc:
        cnvSrc->Lock();
        SetStretchBltMode(hdcSrc, HALFTONE);
        StretchDIBits(
            hdcSrc,
            0,
            0,
            Width,
            Height,
            0,
            0,
            w,
            h,
            buf,
            &bi,
            DIB_RGB_COLORS,
            SRCCOPY
        );
        delete buf;

        // рисуем верхний прямоугольник для статусной строки:
        SelectObject(hdcTitle, hbmTitle);
        TCanvas *cnvTitle = new TCanvas();
        cnvTitle->Handle = hdcTitle;
        cnvTitle->Lock();
        cnvTitle->Brush->Color = clBlack;
        cnvTitle->Rectangle(0, 0, Width, 24);
        BLENDFUNCTION blend = {AC_SRC_OVER, 0, 128, 0};
        // и накладываем его на hdcSrc с использованием альфа-канала:
        ::AlphaBlend(
            hdcSrc,
            0,
            0,
            Width,
            24,
            hdcTitle,
            0,
            0,
            Width,
            24,
            blend
        );

        cnvTitle->Font->Color = clWhite;
        cnvTitle->Font->Size = 14;
        cnvTitle->TextRect(TRect(96, 0, Width + 96, 24), 96, 0, Title);

        if(CvsConnection->CamStatusData[Cam - FCvsConnection->FirstCam].InfoAlarm)
        {
            cnvTitle->Brush->Style = bsSolid;
            cnvTitle->Brush->Color = clRed;
            cnvTitle->Pen->Color = clRed;
            cnvTitle->Ellipse(2, 2, 20, 20);
        }
        if(CvsConnection->CamStatusData[Cam - FCvsConnection->FirstCam].InfoActive)
        {
            cnvTitle->Brush->Style = bsSolid;
            cnvTitle->Brush->Color = clLime;
            cnvTitle->Pen->Color = clLime;
            cnvTitle->Ellipse(24, 2, 44, 20);
        };

        // добавляем на hdcSrc информацию о статусе:
        ::TransparentBlt(
            hdcSrc,
            0,
            0,
            Width,
            24,
            hdcTitle,
            0,
            0,
            Width,
            24,
            clBlack
        );
        cnvTitle->Unlock();
        delete cnvTitle;
        DeleteObject(hbmTitle);
        DeleteDC(hdcTitle);

        // отображаем результат на hdcDst:
        BitBlt(
            hdcDst,
            0,
            0,
            Width,
            Height,
            hdcSrc,
            0,
            0,
            SRCCOPY
        );
        cnvSrc->Unlock();
        Canvas->Unlock();
        delete cnvSrc;
        DeleteObject(hbmSrc);
        DeleteDC(hdcSrc);
    };
}
14
01 сентября 2009 года
Phodopus
3.3K / / 19.06.2008
Исключение небось
991
01 сентября 2009 года
Zenhipster
157 / / 14.01.2005
Не, все оказалось проще. Вопервых обращение
 
Код:
pCvsConnection->pLockStructures->Acquire();

не совсем корректно, потому что pCvsConnection тоже надо защищать.
Поэтому во вложенном классе добавил одноименную ссылку на pLockStructures,
которая инициализируется в его конструкторе.
Во вторых в классе TCvsCamera надо было добавить собственную TCriticalSection,
чтобы нормально отрабатывал этот кусок:

 
Код:
if(CvsConnection->CamStatusData[Cam - FCvsConnection->FirstCam].InfoAlarm)
...

так как тут есть обращение к FCvsConnection из основного и дополнительного потоков.
Правда не обошлось без изврата =)
Код:
void __fastcall TCvsCamera::SetCvsConnection(TCvsConnection *CvsConnection)
{
pCvsCameraCS->Acquire();
try {
    TCvsConnection *OldCvsConnection = FCvsConnection;
    FCvsConnection = CvsConnection;
    if(FCvsConnection)
    {
        if(OldCvsConnection)
            OldCvsConnection->UnRegisterCvsCameraComponent(this);

        FTitle = FCvsConnection->CamName[FCam];
        FCvsConnection->RegisterCvsCameraComponent(this);
    }
    else
    if(OldCvsConnection)
    {
        pCvsCameraCS->Release();
        try {
            OldCvsConnection->UnRegisterCvsCameraComponent(this);
        }
        __finally {
            pCvsCameraCS->Acquire();
        };
    };
    Active = false;
}
__finally {
    pCvsCameraCS->Release();
};
}

Чтобы сделать вызов 'OldCvsConnection->UnRegisterCvsCameraComponent(this);',
пришлось приоткрыть блокировку, может это и нормально )

Ну и одну секцию в поток TCvsConnection::TAlarm, который я тут не расписывал.
Это уже из-за расшаривания CamStatusData.

Теперь работает =)

А то что я описывал в первом посте видимо было следствием разрушения данных.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог