Российский производитель и разработчик сертифицированного измерительного оборудования с 1987 года


Ошибка при считывании данных с карты L791

Вы не вошли.

 Поиск | Регистрация | Вход 

Denis
07.03.2012 07:43:03
#1

Гость

Ошибка при считывании данных с карты L791

Доброго времени суток. Для чего используется EnterCriticalSection() ?  и в каких случаях он может срабатывать?

у меня в самом начале кода, где должно происходить считывание используется EnterCriticalSection(section_harvest), и при обращении к этому событию, вылетает ошибка "EAccesViolation" (вроде так).

Но при этом считывание серийного номера и модели карты проходит без проблем.

Denis
07.03.2012 08:01:35
#2

Гость

Re: Ошибка при считывании данных с карты L791

Если за комментировать, то программа виснет.

вот этот фрагмент:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
ASYNC_PAR DI;
USHORT DI_save = 0;
ULONG i,j;
ULONG savedDI_Count = 0;

        while(true)
        {
           try
           {
           ::Sleep(1);
              //EnterCriticalSection(section_harvest);

            //for (j=0;j<Sync[I_ADC_PCI_COUNT_L791];j++)
           // {
                 DI.s_Type = L_ASYNC_TTL_INP;
                 pI->IoAsync(&DI);
                 DI1 = DI.Data[0]&0x1;

                 Label1->Caption = DI1;

              if (DI1!=DI_save)
              {
                 savedDI_Count++;
                 DI_save = DI1;

              }

                 if (abs((GetTickCount()- StTick))!= 0) {
                 DI_Count = ((savedDI_Count * 1000)/(abs(GetTickCount()- StTick)))/2;}
            //}

                      // if (StopThread_harvest) break;
           }
           __finally
           {
              //LeaveCriticalSection(section_harvest);
              //MessageBox(this->Handle,"Crytical error","",MB_OK);
           }
      }
}

Denis
07.03.2012 08:05:10
#3

Гость

Re: Ошибка при считывании данных с карты L791

кстати, вот эта строка:

for (j=0;j<Sync[I_ADC_PCI_COUNT_L791];j++)

тоже не работает, выдает ошибку. По этому временно за комментировал.

07.03.2012 10:34:51
#4

Сотрудник "Л Кард"
Откуда: Москва
Здесь с 23.04.2014
Сообщений: 3,727

Re: Ошибка при считывании данных с карты L791

а что это за код вообще? У меня таких примеров нет...

Denis
07.03.2012 11:03:31
#5

Гость

Re: Ошибка при считывании данных с карты L791

это индивидуальный пример... программист до меня написал программу (давно еще), теперь мне нужно ее исправлять. Пытаюсь разобраться.

если бесконечный цикл while убрать то вроде как работает все. Но с ним программа виснет. Но по смыслу он нужен.

07.03.2012 14:27:56
#6

Сотрудник "Л Кард"
Откуда: Москва
Здесь с 23.04.2014
Сообщений: 3,727

Re: Ошибка при считывании данных с карты L791

Sync[I_ADC_PCI_COUNT_L791] это счетчик и если сбор активен, то я затрудняюсь сказать что будет... А так чтаются ттл линии. Критическая секция для экслюзивности доступа видимо..

Denis
11.03.2012 06:41:57
#7

Гость

Re: Ошибка при считывании данных с карты L791

Спасибо. А на счет зависания в бесконечном цикле ? Суть в том что точно такой же цикл в оригинале, запускается в отдельном потоке, и все вроде бы работает. Я пытаюсь отдельно сделать пример где только этот цикл, запускается по нажатию кнопки. если делать ограниченное кол-во итераций, то сбор данных проходит нормально. Но мне нужно чтобы он работал постоянно, до момента пока не закрою программу, или не нажму Стоп.

Denis
11.03.2012 11:21:22
#8

Гость

Re: Ошибка при считывании данных с карты L791

решил проблему с зависанием, вместо бесконечного цикла поместил код в Timer. Только теперь вопрос, может ли это повлиять на точность сбора данных ?

11.03.2012 13:17:05
#9

Сотрудник "Л Кард"
Здесь с 18.04.2014
Сообщений: 810

Re: Ошибка при считывании данных с карты L791

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

Ошибка у Вас возникала, очевидно, потому что критическая секция не была создана. Вероятно, в этой программе section_harvest - это указатель (CRITICAL_SECTION* section_harvest), который как-то передается в класс или создается в конструкторе. Так и сам указатель должен быть валидным, и переменная, на которую он ссылается, должна быть проинициализирована вызовом InitializeCriticalSection.

Вообще шаблон использования критической секции примерно такой:

/* глобальная переменная */
CRITICAL_SECTION my_cs;

/* какие-то защищенные данные */
volatile struct my_struct protected_data;

/* в основной программе до старта потоков, один раз */
InitializeCriticalSection(&my_cs);

/* в потоках, обращающихся к данным, защищенным критической секцией */
EnterCriticalSection(&my_cs);
...обращения к protected_data только тут...
...если в это время другой поток попытается сделать Enter в эту же критическую секцию, то он будет ждать до тех пор, пока этот поток не сделает Leave...
LeaveCriticalSection(&my_cs);

/* в основной программе после останова потоков, один раз */
DeleteCriticalSection(&my_cs);

КРИТИЧНО, что на каждый Enter должен быть Leave - например, if (error_occured) return 0 или исключение в C++ после EnterCriticalSection приведет к тому, что все остальные потоки зависнут в ожидании. Именно поэтому Ваш предшественник поместил Leave в блок finally.

Альтернативный более красивый способ для C++

/*================================================================================================*
* Классы для автоматического использования критических секций.
* TCritical: создает/удаляет критическую секцию.
* TCSLock: захватывает критическую секцию на время жизни экземпляра.
* Пример использования:
* class TMyClass
*     {
*     TCritical cs;
*     int DoExclusive(void)
*         { TCSLock lock(cs); ... return 1; }
*     };
*================================================================================================*/
class TCritical
    {
private:
    CRITICAL_SECTION critical_section;
public:
    TCritical()
        { InitializeCriticalSection(&critical_section); }
    ~TCritical()
        { DeleteCriticalSection(&critical_section); }
    void Enter()
        { EnterCriticalSection(&critical_section); }
    void Leave()
        { LeaveCriticalSection(&critical_section); }
    };

class TCSLock
    {
private:
    TCritical &cs_object;
public:
    TCSLock(TCritical &critical)
        : cs_object(critical)
        { cs_object.Enter(); }
     ~TCSLock()
        { cs_object.Leave(); }
    };
/*================================================================================================*/

Denis
12.03.2012 06:29:54
#10

Гость

Re: Ошибка при считывании данных с карты L791

Александр Е, Спасибо!) Теперь все начинает вставать на свои места)

Контакты

Адрес: 117105, Москва, Варшавское шоссе, д. 5, корп. 4

Многоканальный телефон:+7 (495) 785-95-25

Письма и запросы: lcard@lcard.ru
Отдел продаж: sale@lcard.ru
Техническая поддержка: support@lcard.ru

Время работы: с 9-00 до 19-00 мск