berkov Temat założony przez niniejszego użytkownika |
[ADO C++] Obsluga Event'ow.( Obiekt - Connection, Event - ExecuteComplete) » 2013-12-09 18:38:11 Hey ho.. taka sytuacja.... Z WINAPI lacze sie przez ADO do MS Access'a, w taki oto sposob: ADODB::_ConnectionPtr connection; ADODB::_RecordsetPtr recordset; HRESULT hr;
hr = CoInitialize( NULL ); if( FAILED( hr ) ) { MessageBox( 0, "IMS Error Handler - Blad 0202 - Brak inicjacji bibliotek COM", "Blad 0202", 0 ); }
hr = connection.CreateInstance( __uuidof( ADODB::Connection ) ); if( FAILED( hr ) ) { MessageBox( 0, "IMS error handler - Blad 0203 - Brak deklaracji _ConnectionPtr ADO", "Blad 0203", 0 ); }
hr = recordset.CreateInstance( __uuidof( ADODB::Recordset ) ); if( FAILED( hr ) ) { MessageBox( 0, "IMS error handler - Blad 0204 - Brak deklaracji _RecordsetPtr ADO", "Blad 0204", 0 ); }
try { connection->CursorLocation = ADODB::adUseClient; } catch( _com_error blad ) { errorhandler( blad, "0205" ); }
try { connection->Open( "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + dbpath + ";Jet OLEDB:Database Password=xxx;", "", "", ADODB::adConnectUnspecified ); } catch( _com_error blad ) { errorhandler( blad, "0206" ); CoUninitialize(); PostQuitMessage( 0 ); }
.. i teraz zwykla petla for wpisuje spora ilosc rekordow do bazy, rekordy same w sobie nie sa duze ale jest ich sporo, zazwyczaj powyzej 100, no i nastepuja od razu po sobie: try { for( long i = 0; i <= jakaszmienna; i++ ) { query = "INSERT INTO PLATN (" "pl_data, " "pl_user, " "ko_id, " "pl_status, " "pl_rodzaj, " "pl_kwota, " "pl_oproc, " "pl_odsetki, " "pl_kolejnosc, " "pl_datapl, " "pl_reminder, " "pl_datazapl, " "pl_opis " ") VALUES (" + Przecinek2Kropka(( _bstr_t )( double ) PL->list[ i ]->pl_data ) + ",'" +( _bstr_t ) PL->list[ i ]->pl_user + "'," +( _bstr_t ) PL->list[ i ]->ko_id + "," +( _bstr_t ) PL->list[ i ]->pl_status + "," +( _bstr_t ) PL->list[ i ]->pl_rodzaj + "," + Przecinek2Kropka(( _bstr_t )( double ) PL->list[ i ]->pl_kwota ) + "," +( _bstr_t ) PL->list[ i ]->pl_oproc + "," + Przecinek2Kropka(( _bstr_t )( double ) PL->list[ i ]->pl_odsetki ) + "," +( _bstr_t ) PL->list[ i ]->pl_kolejnosc + "," +( _bstr_t )( int ) PL->list[ i ]->pl_datapl + "," +( _bstr_t )( int ) PL->list[ i ]->pl_reminder + "," +( _bstr_t )( int ) PL->list[ i ]->pl_datazapl + ",'" +( _bstr_t ) PL->list[ i ]->pl_opis + "'" + ")"; connection->Execute( query, 0, 0 ); } } catch( _com_error blad ) { errorhandler( blad, "0217" ); CoUninitialize(); }
connection->Close(); CoUninitialize();
no i wlasnie w momencie connection-> Execute (query, 0,0) zaczynaja sie schody... Wynika to z tego ze Execute nie czeka az skonczy sie wykonywac, kod poprostu leci dalej, i petla zazwyczaj wpisze od 10 do 50 rekordow i wyrzuci blad poniewaz kod wykona sie czasami szybciej niz execute zdarzy zapisac caly rekord. Probowalem uzyc polaczenia asynchronicznego connection-> Execute (query, 0,ADODB::adAsyncExecute); ale doczytalem ze Access nie wspiera polaczen "rownoleglych" i najprawdopodobniej jedynym sposobem jest uzycie eventow. Innymi slowy chce zatrzymac moja petle for dopoki nie dostane powiadomienia "ExecuteComplete". Problem tylko w tym ze dokumentacja MSDN na temat uzycia eventow w ADO to jakas masakra. Czuje sie jakbym czytal po chinsku. http://msdn.microsoft.com/en-us/library/windows/desktop/ms675794(v=vs.85).aspx kompletnie nic z tego nie zrozumialem.. Czy ktos wie jak (albo zna strone ktora opisue jak) uzyc eventu ExecuteComplete (ale dla C++ a nie dla VB ktorego jest w cholere i jeszcze troche)? Chodzi tylko o to zeby powstrzymac petle for dopoki Execute nie wykona sie calkowicie ... Dzieki. b |
|
DejaVu |
» 2013-12-10 01:32:44 |
|
berkov Temat założony przez niniejszego użytkownika |
» 2013-12-10 10:54:14 @DejaVu, dzieki za odpowiedz.. ten pierwszy link raczej nie byl przydatny, bo tam opisane jest tylko uzycie progress bara ale dalej nie mowi nic o tym jak poczekac do zakonczenia query, drugi link to o ODB... Ale przyznaje ze nie wpadlem na pomysl wrzucenia tego do jednego query... problem pojawil sie tylko w tym ze nagle moj _bstr_t string urosl do ogromnych rozmiarow i zaczal wyrzucac bledy dotycxace pamieci choc pracowalem na komputerze z 8GB ramu co dalo mi do myslenia.. spedzilem wiec kilka kolejnych godziny na debugowaniu zeby wychwycic gdzie dokladnie pojawia sie blad (nie bylo to proste bo pojawia sie raz na 100 - 1000 przyapdkow) pozatym blad ten tez nie byl zawsze taki sam, czasami error handler go wychwycil pisza ze np string query nie jest poprawny a czasami (zazwyczaj) wyrzucilo to: xxx.exe has triggered a breakpoint i wskazalo na plik biblioteki free.c: void __cdecl _free_base( void * pBlock ) { int retval = 0; if( pBlock == NULL ) return; RTCCALLBACK( _RTC_Free_hook,( pBlock, 0 ) ); retval = HeapFree( _crtheap, 0, pBlock ); if( retval == 0 ) { errno = _get_errno_from_oserr( GetLastError() ); } }
lub biblioteka malloc.c: __forceinline void * __cdecl _heap_alloc( size_t size )
{ if( _crtheap == 0 ) { _FF_MSGBANNER(); _NMSG_WRITE( _RT_CRT_NOTINIT ); __crtExitProcess( 255 ); } return HeapAlloc( _crtheap, 0, size ? size: 1 ); }
najdziwniejsze jest to ze jak program puscielem normalnie z pod windowsa (nie z pod kompilatora) to zawsze wszystko jest ok i query sie konczylo bez problemu, nawet jak poscilem za soba 1000 razy kazdy rekord z osobna (moj pierwotny kod)... wszystko dzialala cacy.... wychwycilem ze problem wyrzuca zazwyczaj w mojej funkcji Przecinek2Kropka, ktora wyglada tak: _bstr_t Przecinek2Kropka( _bstr_t source ) { char * temp = new char[ 50 ]; temp = _com_util::ConvertBSTRToString( source ); for( int i = 0; i < 50; i = i + 1 ) { if( temp[ i ] == ',' ) { temp[ i ] = '.'; } } _bstr_t wynik = temp; delete[] temp; return wynik; } okazalo sie ze wystarzylo wykomentowac if (temp[i] == ',') (...) i program zaczal dzialac bez problemu nawet uruchomiony z pod kompilatora (MS VS Express 2010)... oczywiscie ten if tam musi byc.. wiec teaz pytanie brzmi dlaczego moj IF nie dziala i dlaczego tylko jak program uruchomiony jest z pod kompilatora? dzieki b p.s. gdyby ktos dalej wiedzial jak uzyc eventow to bede wdzieczny, mysle ze moga sie przydac na przyszlosc... |
|
DejaVu |
» 2013-12-10 12:26:09 Może nie masz zakończonego łańcucha znaków znakiem terminalnym? |
|
berkov Temat założony przez niniejszego użytkownika |
» 2013-12-10 12:27:00 Juz wiem.. ConvertBSTRToString skraca moj string dodajac na koncu \0 wiec siegajac do tablicy poza \0 powoduje blad... Kompilator tego pilnuje ale zwykly runtime pod windowsem dopoki nie chce dostepu do czegos poza moim program co jest akurat zajete przez inny program nie sposowuje wyjatku i bledu.... kod powinien wygaldac tak: _bstr_t Przecinek2Kropka( _bstr_t source ) { int dl = source.length(); char * temp = new char[ dl + 1 ]; temp = _com_util::ConvertBSTRToString( source ); for( int i = 0; i <= dl; i = i + 1 ) { if( temp[ i ] == ',' ) { temp[ i ] = '.'; } } _bstr_t wynik = temp; delete[] temp; return wynik; }
|
|
berkov Temat założony przez niniejszego użytkownika |
» 2013-12-10 12:36:57 No nic.. wracajac do temuatu Events w ADO.. gdyby ktos mial zrozumiale dla przecietnego zjadacza chleba informacje "jak i z czym" to z gory dziekuje. Problem sam w sobie chociaz nie dotyczyl glownego watku jak poczatkowo myslalem jest rozwiazany. dzieki |
|
Monika90 |
» 2013-12-10 16:48:39 char * temp = new char[ dl + 1 ]; temp = _com_util::ConvertBSTRToString( source );
To się nazywa memory leak |
|
berkov Temat założony przez niniejszego użytkownika |
» 2013-12-10 19:29:34 czemu? |
|
« 1 » 2 |