Entwickler-Ecke
Datenbanken - FireDAC Connection Definition Problem
NOS1971 - Do 24.07.14 13:25
Titel: FireDAC Connection Definition Problem
Hallo zusammen,
ich habe ein Problem eine Connection Definiton zu erzeugen für meine multithreaded anwendung. ich nutze folgenden code und es erscheint die im anhang sichtbare fehlermeldung obwohl ich alles laut doku mache.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| if FDManager.IsConnectionDef(ConDefName) then begin FDManager.DeleteConnectionDef(ConDefName); end; condef := TStringList.Create; condef.Add('Database=' + FResultDataBaseFileName); condef.Add('SharedCache=False'); condef.Add('LockingMode=Normal'); condef.Add('Synchronous=Full'); condef.Add('LockingMode=Normal'); condef.Add('CacheSize=60000'); condef.Add('BusyTimeOut=30000'); condef.Add('Pooled=True'); condef.Add('POOL_MaximumItems=' + IntToStr(FMaxThreadPoolCount + 1)); FDManager.AddConnectionDef(ConDefName,'SQLite',condef);
. . . FDManager.Active := True;
. . .
|
Code aus dem thread:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| var oConn: TFDConnection; begin FreeOnTerminate := False; oConn := TFDConnection.Create(nil); oConn.ConnectionDefName := 'SQLite_Threaded_Pooled'; try oConn.Connected := True; while not Terminated do begin
end; finally oConn.Free; end; end; |
zuma - Do 24.07.14 13:56
ich hab keine Ahnung von Firedac, aber könnte es sein,
das du im oberen Beispiel deine Connection 'SQLite' mit ConDefName (was auch immer drin steht) benennst
und im unteren Beispiel aber versuchst, eine Connection mit dem Namen 'SQLite_Threaded_Pooled' zu verwenden ?
evtl. besser immer ConDefName nutzen ?
klingt für mich so, als könne man da mehrere Connections ablegen und
dann wählen (über den Namen der einzelnen Connections), welche man nehmen will ?
falls ich völlig daneben lieg, einfach diesen Post ignorieren :mrgreen:
zuma
jaenicke - Do 24.07.14 13:57
Ich weiß nicht warum du die Verbindungsdefinition per Stringliste hinzufügst. Wir machen das so direkt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| var oDef: IFDStanConnectionDef; begin oDef := FDManager.ConnectionDefs.FindConnectionDef('SQLite_Threaded_Pooled'); if not Assigned(oDef) then oDef := FDManager.ConnectionDefs.AddConnectionDef; oDef.Name := 'SQLite_Threaded_Pooled'; oDef.DriverID := 'SQLite'; oDef.Database := FResultDataBaseFileName; oDef.UserName := ...; oDef.Password := ...; oDef.Apply; |
zuma hat folgendes geschrieben : |
ich hab keine Ahnung von Firedac, aber könnte es sein,
das du im oberen Beispiel deine Connection 'SQLite' mit ConDefName (was auch immer drin steht) benennst
und im unteren Beispiel aber versuchst, eine Connection mit dem Namen 'SQLite_Threaded_Pooled' zu verwenden ? |
SQLite ist der Name des Treibers.
NOS1971 - Do 24.07.14 17:07
HI,
ok .. habe ich so umgebaut .. so ist die verbindung nicht mehr provate sondern persistent ... aber der fehler lag woander ...
Viele dank :-)
NOS1971 - Do 24.07.14 17:26
Das funktioniert soweit einwandfrei ....
nun bleibt nur noch das problem das wenn ich mehr als einen thread erzeuge die threads nicht mehr korrekt beendet werden und das proggi komplett im nirvana hängt .... ich habs ja shcon aus dem websitespider rausgenommen um mich diesem problem zu widmen aber es haut nicht hin
vielleicht seht ihr hier die kleinigkeit die das problem verursacht ... und ich tippe mal dass es auch ne kleinigkeit ist
hier das hauptobjekt
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111:
|
constructor TMultiThreadedWebAnalyser.Create; begin inherited Create; ResultURLDictionary := TObjectDictionary<string, TURLNodeTreeData>.Create([doOwnsValues]); ProgressData := TProgressData.Create; end;
destructor TMultiThreadedWebAnalyser.Destroy; begin ResultURLDictionary.Free; ResultURLDictionary := nil; FProgressData.Free; FProgressData := nil; inherited; end;
procedure TMultiThreadedWebAnalyser.Pause; begin
end;
procedure TMultiThreadedWebAnalyser.Reset; begin if ResultURLDictionary <> nil then begin ResultURLDictionary.Free; ResultURLDictionary := nil; end; ResultURLDictionary := TObjectDictionary<string, TURLNodeTreeData>.Create([doOwnsValues]); FCancelled := false; FAnalyserStatus := asIdle; FMaxThreadPoolCount := 10; FProgressData.Added := 0; FProgressData.Analysed := 0; FProgressData.ActiveThreads := 0; FProgressData.Processed := 0; end;
procedure TMultiThreadedWebAnalyser.Resume; begin
end;
procedure TMultiThreadedWebAnalyser.Start; var threadcounter: integer; condef: IFDStanConnectionDef; begin FAnalyserStatus := asBusy; FCancelled := false; condef := FDManager.ConnectionDefs.FindConnectionDef(ConDefName); if not Assigned(condef) then condef := FDManager.ConnectionDefs.AddConnectionDef; condef.Name := ConDefName; condef.DriverID := 'SQLite'; condef.Database := FResultDataBaseFileName; condef.Pooled := true; condef.UserName := ''; condef.Password := ''; condef.Params.Add('SharedCache=False'); condef.Params.Add('LockingMode=Normal'); condef.Params.Add('Synchronous=Full'); condef.Params.Add('LockingMode=Normal'); condef.Params.Add('CacheSize=60000'); condef.Params.Add('BusyTimeOut=30000'); condef.Params.Add('POOL_MaximumItems=' + IntToStr(FMaxThreadPoolCount + 1)); condef.Apply; FDManager.Active := True; SetLength(FURLAnalyserThreadPool,FMaxThreadPoolCount); for threadcounter := 0 to FMaxThreadPoolCount - 1 do begin FURLAnalyserThreadPool[threadcounter] := TURLAnalyser.Create; end; end;
procedure TMultiThreadedWebAnalyser.Stop; var threadcounter: integer; begin FDManager.CloseConnectionDef(ConDefName); for threadcounter := FMaxThreadPoolCount - 1 downto 0 do begin TURLAnalyser(FURLAnalyserThreadPool[threadcounter]).Terminate; end; for threadcounter := FMaxThreadPoolCount - 1 downto 0 do begin TURLAnalyser(FURLAnalyserThreadPool[threadcounter]).WaitFor; TURLAnalyser(FURLAnalyserThreadPool[threadcounter]).Free; end; FAnalyserStatus := asIdle; end; |
und hier der code des/der threads
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
|
procedure TURLAnalyser.Execute; var oConn: TFDConnection; begin FreeOnTerminate := False; oConn := TFDConnection.Create(nil); oConn.ConnectionDefName := ConDefName; try oConn.Connected := True; while not Terminated do begin
end; finally oConn.Free; end; end; |
NOS1971 - So 27.07.14 18:06
Also das Threading an sich ist nun stabil .... allerdings gibt es noch ein paar probleme ...
ich habe nun in jedem thread eine connection und dazu 2 queries .... ist das ok oder darf es nur eine sein ?
ich nutze eine um das aktuelle item aus der db zu holen welches ich bearbeite ... das halte ich offen und mache eine analyse ... am ende der analyse aktualisiere ich es ... in einer procedure die aus der analyse aufgerufen wird und zum thread gehört adde ich über eine zweite wuery daten in die db
weiterhin stelle ich fest das trotz laufender threads nur einer einen gültigen datensatz zum bearbeiten aus der db holt ... als wenn der rest geblockt ist ...
any idea ?
hk - So 03.08.14 16:43
NOS1971 hat folgendes geschrieben : |
ich habe nun in jedem thread eine connection und dazu 2 queries .... ist das ok oder darf es nur eine sein ?
|
Hallo. Eine Connection je Thread ist richtig, siehe auch
http://docwiki.embarcadero.com/RADStudio/XE6/de/Multithreading_%28FireDAC%29
"Die Standardvereinfachung besteht im Erstellen und Verwenden eines zugehörigen Verbindungsobjekts zur Arbeit mit der Datenbank für jeden Thread. In diesem Fall ist keine zusätzliche Serialisierung erforderlich."
Ich habe auch so meine Probleme beim ersten Umgang mit FireDAC. Zum Beispiel
Delphi-Quelltext
1: 2: 3: 4:
| if FDManager.IsConnectionDef('MSSQL_Connection') then FDManager.DeleteConnectionDef('MSSQL_Connection'); if FDManager.IsConnectionDef('MSSQL_Connection') then showmessage('immer noch vorhanden'); |
Gruß, hk
NOS1971 - So 03.08.14 17:13
also bei mir will das einfach nicht hinhauen und ich habe wirklich keinen plan warum das mit dem pooling nicht funktioniert.
Das mit den Conectiondefinitions habe ich so gemacht
Delphi-Quelltext
1: 2:
| var condef: IFDStanConnectionDef; |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| FDManager.Close; condef := FDManager.ConnectionDefs.FindConnectionDef(ConDefName); if not Assigned(condef) then condef := FDManager.ConnectionDefs.AddConnectionDef; condef.Name := ConDefName; condef.DriverID := 'SQLite'; condef.Database := FResultDataBaseFileName; condef.Pooled := true; condef.UserName := ''; condef.Password := ''; condef.Params.Add('SharedCache=False'); condef.Params.Add('LockingMode=Normal'); condef.Params.Add('Synchronous=Full'); condef.Params.Add('LockingMode=Normal'); condef.Params.Add('CacheSize=60000'); condef.Params.Add('BusyTimeOut=30000'); condef.Params.Add('POOL_MaximumItems=' + IntToStr(FMaxThreadPoolCount + 1)); condef.Apply; FDManager.Active := True; |
das funktioniert super ... ich habe so das gefühl das das schreiben aus einem query im thread über die connection des threads probleme macht solange das andere query einen datensatz über die gleiche connection offen hält.
hk - So 03.08.14 17:24
NOS1971 hat folgendes geschrieben : |
ich habe so das gefühl das das schreiben aus einem query im thread über die connection des threads probleme macht solange das andere query einen datensatz über die gleiche connection offen hält. |
Greifen die beide Queries auf dieselbe Tabelle zu? Dann könnte es wohl Probleme geben.
Ich muss mich aber auch erst noch in FireDAC einarbeiten.
NOS1971 - So 03.08.14 19:20
Ja .... beide Queries greifen auf die selbe tabelle zu ...
es ist eine Webseitenanalysesoftware und der kern, also quasi der crawler, ist multithreaded .... so hole ich mir quasi mit der einem query des threads die nächste zu analysierende url aus der tabelle und halte den datensatz offen während die andere query die daten der gefundenen urls in die tabelle schreibt.
da habe ich auch noch keine wirklich funktionierende lösung gefunden ... auch ohne firedac lief das nicht besonders sauber ... ich dachte eigentlich es wird durch die query nur der datensatz geblockt und nicht die tabelle.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!