Autor Beitrag
NOS
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: Fr 23.09.16 14:12 
Hallo zusammen,

ich habe, wie einige schon in dem ein und anderen Post von mir gelesen haben, einen WebsiteAnalyser in Arbeit. Ich crawle also Multithreaded die URL's und speichere die Analysedaten für jede URL in die DB. Zu aktuellen Anzeige habe ich bisher einen TVirtualStringTree genommen was auch super geklappt hat.

Nun möchte ich dem User die Möglichkeit geben hier auch eine URL zu suchen oder zu filtern. Nun stellt sich mir die Frage ob ich:

1. Ein DBGrid nehmen könnte welches sich zur Laufzeit aktualisiert

2. Den Progress während der Analyse ohne Tabelle gestalte und nur die Ergebnistabelle zum Schluss in ein DBGrid lade

3. Filterfunktionalität und Suche zum TVirtualStringTree hinzufügen

Mich würde eure Meinung interessieren und natürlich auch Infos zu Punkt 1 falls dies gehen sollte.

Threadobjekte sind selbstgecodet und als DB nutze ich Firebird embedded mit Connectionpooling.

Ich freue mich auf eure Antworten,

Grüße und Dank,

Andreas
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2165
Erhaltene Danke: 399

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Fr 23.09.16 21:57 
Guten Abend NOS,

wenn du das DataSet vom TDataSource aktualisierst (.Refresh), müsste das DBGrid entsprechend reagieren. Und die anderen Punkte sind wohl geschmackssache. ;)

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)

Für diesen Beitrag haben gedankt: NOS
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: Sa 24.09.16 18:34 
Ok .... dann werde ich das mal so ausprobieren ... vielen Dank :-)
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: So 25.09.16 00:47 
Vom Prinzip her hat es geklappt .... aber seitdem friert mein gui immer ein obwohl die abfrage im async mode ist ... gibt es da noch etwas zu beachten wenn X Threads in die db schreiben und ich gleichzeitig den progress mit ner connection anzeigen will ?
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2165
Erhaltene Danke: 399

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: So 25.09.16 10:35 
Das kann ich dir nicht beantworten, da ich sowas bis datto nie gebraucht habe. Die Anwendung friert ein, sobald die Aktualisierung des DataSet stattfindet? Bei welcher Gelegenheit (Ereignis, Methode) wird die Aktualisierung durchgeführt? Und was machen die Threads genau, nur Datensätze schreiben?

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: So 25.09.16 10:49 
Es friert nach einer Zeit ein ... ich denke es liegt daran dass das eine Refresh noch nicht fertig ist und ich es erneut calle ... gibt es ne Möglichkeit darauf zu warten ???

Es ist so dass es zwischen 1 und 100 Threads gibt die jeweils einen Quellcode von einer URL downloaden, parsen und die ergebnisse nebst der neuen URLs in die DB schreiben. Aus der DB gelesen wird nicht ausser durch die connection / query die die liste aktualisieren soll.

Es ist auch völlig egal ob ich mit einem oder mit 10 threads analysiere
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2165
Erhaltene Danke: 399

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: So 25.09.16 22:53 
Klingt für mich als würde die Abfrage des Quelltextes (mittels TIdHttp.Get/Head/Post ?) das Einfrieren hervorrufen. Benutz' parallel dazu die TIdAntiFreeze Komponente, bzw. wenn du es zur Laufzeit erzeugst:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
var
  http: TIdHttp;
  freeze: TIdAntiFreeze;
  html: string;
begin
  http := TIdHttp.Create(nil);
  try
    freeze := TIdAntiFreeze.Create(nil);
    try
      freeze.Active := true;
      html := http.Get('http://www.google.de');
      showmessage(html);
    finally
      freeze.Free;
    end;
  finally
    http.Free;
  end;
end;


Oder du setzt Application.ProcessMessage, nachdem du den Quelltext ausgelesen hast.
Einen Thread kannst du mit .Resume forsetzen und mit .Suspend pausieren, sofern du Suspend nicht schon im Konstruktor des Thread auf true gesetzt hast.
Eine weitere Möglichkeit wäre, wenn du das DataSet.DisableControls setzt, anschließend deine Datensätze schreibst, und am Ende wieder DataSet.EnableControls setzt.
Das verhält sich in etwa so wie .BeginUpdate und .EndUpdate bei manchen Editier-Feldern.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: Mo 26.09.16 09:06 
Moin .... also das ganze Multithreadinggebilde mit idHTTP etc. ist vollkommen ok und läuft stabil.

Wenn ich das Refreshen der Hauptansicht auskommentiere (also das .Refresh des DataSet des DBGrid) läuft auch alles problemlos, sowie vorher mit dem VirtualStringTree auch. Es muss also am Refresh der Hauptansicht liegen die ich eingebaut habe.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18686
Erhaltene Danke: 1619

W10 x64 (Chrome, IE11)
Delphi 10.2 Ent, Oxygene, C# (VS 2015), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 26.09.16 10:17 
Der VirtualStringTree kann doch schon selbst filtern. Einfach nur durchiterieren und Filtered für die einzelnen Nodes setzen. Das geht blitzschnell, selbst bei vielen tausend Einträgen.

_________________
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!

Für diesen Beitrag haben gedankt: NOS
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: Mo 26.09.16 11:09 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Der VirtualStringTree kann doch schon selbst filtern. Einfach nur durchiterieren und Filtered für die einzelnen Nodes setzen. Das geht blitzschnell, selbst bei vielen tausend Einträgen.



Also ist das die bessere Variante als das mit einem DBGrid zu versuchen ?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18686
Erhaltene Danke: 1619

W10 x64 (Chrome, IE11)
Delphi 10.2 Ent, Oxygene, C# (VS 2015), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 27.09.16 04:49 
In Anbetracht der Tatsache, dass das ja ansonsten schon so funktioniert, würde ich sagen ja.

Ob es insgesamt die beste Lösung ist, kann ich nicht so aus dem Stegreif sagen. Mit großen Datenmengen habe ich bisher nur mit einer VirtualStringTree gearbeitet.

_________________
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!

Für diesen Beitrag haben gedankt: NOS
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: Di 27.09.16 08:04 
Ok ... dann lasse ich erstmal die finger davon .... habe den source mit dem dbgrid gesichert und widme mich anderen dingen :)
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1137
Erhaltene Danke: 75

Win7
DXE2 Prof, Lazarus
BeitragVerfasst: Mi 28.09.16 09:10 
Von wo aus wird das Refresh aufgerufen? Nicht aus den WorkerThreads, hoffe ich mal. Das musst Du via Timer auf deinem Form machen. Dann kommen die Refesh auch nacheinander und nicht gleichzeitig.
Intervall kannst Du dann ja Nutzerseitig festlegen lassen.

_________________
Solange keine Zeile Code geschrieben ist, läuft ein Programm immer fehlerfrei.
Ich teste nicht, weil ich Angst habe Fehler zu finden.
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: Mi 28.09.16 09:42 
Die Refreshes kamen vom Mainform aus nem Event den ich aus dem Distrubtorthread gecalled habe ... also nach jeder Änderung ein Call ... aber das ist wohl zu schnell hintereinander
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: Mi 28.09.16 10:04 
Gibt es denn keine Möglichkeit zu warten bis das erste refresh abgearbeitet wurde und dann ein neues zu machen ? Wäre doch das sinnigste bei konstant anwahsenden datenbanken und multithreading ... oder ?
Nersgatt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1558
Erhaltene Danke: 267


Delphi 10 Seattle Prof.
BeitragVerfasst: Mi 28.09.16 10:56 
user profile iconNOS hat folgendes geschrieben Zum zitierten Posting springen:
Die Refreshes kamen vom Mainform aus nem Event den ich aus dem Distrubtorthread gecalled habe ... also nach jeder Änderung ein Call ... aber das ist wohl zu schnell hintereinander


Wenn Du im Thread einen Event auslöst, dann wird der Eventhandler im Threadkontext abgearbeitet!
Lösen kannst Du das, indem Du den Eventhandler mit Synchronize aufrufst. Mit einer anonymen Methoden ist das Probemlos und schnell zu machen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TMeinThread.DoWeltformelGefunden;
begin

  if assigned(FOnWeltformelGefunden) then
  begin
    Synchronize(procedure
      begin
        FOnWeltformelGefunden;
      end);
  end;

end;


Auf diese Art wird der Eventhandler im Kontext des Mainthreads aufgerufen. Dort kannst Du dann auch problemlos Sachen machen, die Du innerhalb des Threads nicht machen dürftest (Zugriffe auf Steuerelemente zum Beispiel).

_________________
Gruß, Jens
Zuerst ignorieren sie dich, dann lachen sie über dich, dann bekämpfen sie dich und dann gewinnst du. (Mahatma Gandhi)

Für diesen Beitrag haben gedankt: NOS
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: Mi 28.09.16 12:50 
@Nersgatt

vielleicht habe ich das falsch ausgedrückt ... also der Distributorthread verteilt die URLs zur Analyse an die URLWorkerthreads. Jedes mal wenn der Distributorsthread neue Arbeit verteilt mache ich ein PostMessage. Im Mainform wird die Message dann empfangen und hier das Refresh des FdQuery ausgeführt.

Mir geht es darum festzustellen ob das Refresh des Query schon abgearbeitet ist oder nicht. Dann so friert irgendwann alles ein weil stängi FdQuery.Refresh gecalled wird.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18686
Erhaltene Danke: 1619

W10 x64 (Chrome, IE11)
Delphi 10.2 Ent, Oxygene, C# (VS 2015), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 28.09.16 12:54 
Wenn das Refresh im Hauptthread ausgeführt wird, kann es auch nicht parallel mehrfach ausgelöst werden. Allerdings natürlich schnell hintereinander. Deshalb würde ich dort einen Lastenausgleich einbauen.

Zum Beispiel indem du einen Timer startest und diesen erst das Refresh ausführen lässt. Kommen vor dessen Ausführung noch weitere Refreshanforderungen an, werden diese verschluckt. Das mag nicht die schönste Lösung sein, aber eine einfache.

_________________
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!

Für diesen Beitrag haben gedankt: NOS
NOS Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 178
Erhaltene Danke: 2

Win XP, Win Vista Ultimate, Win 7 Ultimate
Delphi 10 - Seattle PRO
BeitragVerfasst: Mi 28.09.16 14:37 
Ich habe jetzt den TFdQuery.AfterRefesh genommen und ein Flag gesetzt ... somit läuft immer nur ein refresh .... sieht etwas ruckelig aus von den intervallen wenn es aktualisiert aber schonmal stabil bisher :-) kann man die "Flüssigkeit" des refresh beeinflussen oder ist das einfach so ?
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1137
Erhaltene Danke: 75

Win7
DXE2 Prof, Lazarus
BeitragVerfasst: Mi 28.09.16 15:39 
Verhinderst Du damit jetzt dass, während ein Refresh läuft, weitere Messages gepostet werden können? Denn sonst stapelt es sich ja weiter wie bisher und alles Refreshes werden abgearbeitet auch wenn schon lange der Endstand erreicht und angezeigt ist.

_________________
Solange keine Zeile Code geschrieben ist, läuft ein Programm immer fehlerfrei.
Ich teste nicht, weil ich Angst habe Fehler zu finden.