i am new to Threads, i have a List contains a strings. My goal is to make multiple threads do work to this List, this codes only for a single thread because i'm learning currently, however i get AV when i press start Button.
type
TDemoThread = class(TThread)
private
procedure Abort;
protected
procedure Execute; override;
public
List: TStringList;
end;
procedure TfrmMain.StartButton1Click(Sender: TObject);
var
i: integer;
List: Tstrings;
begin
for i := 0 to memo1.Lines.Count - 1 do
begin
List := TStringList.Create;
List.Add(memo1.Lines.Strings[i]);
end;
Thread := TDemoThread.Create(True);
Thread.FreeOnTerminate := True;
Thread.Start;
end;
procedure TDemoThread.Execute;
var
lHTTP: TIdHTTP;
i: integer;
X: Tstrings;
begin
inherited;
if Terminated then
Exit;
lHTTP := TIdHTTP.Create(nil);
X := TStringList.Create;
lHTTP.ReadTimeout := 30000;
lHTTP.HandleRedirects := True;
for i := 0 to List.Count - 1 do
try
X.Text := lHTTP.Get('https://instagram.com/' + List.Strings[i]);
S := ExtractDelimitedString(X.Text);
X.Clear;
TThread.Synchronize(nil,
procedure
begin
frmMain.Memo2.Lines.Add(List.Strings[i] + ' : ' + S);
end);
finally
end;
end;
Personally I'd avoid updating the form from the threads themselves. Threads are data generators here, not GUI managers. So let them separate their concerns.
I'd make all the threads accumulate the results into the same shared container and then make a GUI thread to poll that container instead. Human eyes are slow and Windows GUI is slow too, so you should not update your GUI more often than 2 or 3 times per second. It would only waste CPU load and blur the form into being unreadable.
Another thing would be to avoid using slow
TStringList
unless its extra functionality (which makes it slow) is required. The regularTList<string>
is more than enough as a dumb container and is faster.PS. Personally, I'd also use OmniThreads Library, as it generally makes maintaining data-generating threads easier. For example just managing how many threads did you created becomes setting one property and determining when all threads complete their work is another oneliner. You really should not create a thousand of threads to fetch all the URLs, instead you should have 10-20 threads in a
Thread Pool
that would take the URLs from aInput Queue
and fetch them one after another. I suggest you reading about OTL'sParallel For
andFork-Join
patterns at http://otl.17slon.com/tutorials.htm - it would allow making such an application more concise and easier to write.Pipeline
pattern would probably be even better match for this task - since you anyway prepare URLs list as a source collection. Half the scaffolding inStartButtonClick
would be gone, and the wholeTDemoThread
class too.Your problem is that you never assign to the
List
member of the thread class:Hence the access violation.
It looks like you are trying to pass the contents of
memo1
to the thread. I would do that like so:It is pointless to create suspended and then immediately start. It is also not permitted to hold a reference to a
FreeOnTerminate
thread after it has started so I removed that.The code in
TDemoThread.Execute
leaks, unless you are running exclusively on an ARC platform. And the try/finally is pointless. And you don't need a string list to hold a singlestring
. Assuming you aren't using ARC it should be: