Depends whether you want you app to be as responsive as OE, or
actually useable. Threads are not too bad, though I agree that there
is a learning gentle-slope-with-lumps.
> And just in case I have to, does someone know how? Cuz from my
small level
> of experience with threads, I've found that you get errors if you
try to
> access it from outside the thread, or from another thread, and I'd
need full
> access to the TIdNNTP component, or something like that.
It's not a problem once you've done it a couple times. Typically,
with these sort of protocols, the thread runs a loop where it waits
for a command, executes it when it arrives, returns the result, (or
exception message), and waits for another command. you can send a
command by setting a command enumerateed field in the thread and then
calling 'resume' - the thread could suspend itself when done. My
favourite for simple control is a TsimpleEvent 'go' flag - load in
the command, set the event & off it goes. Alternatively, it's not
difficult to create a Windows message queue for the thread & send it
commands that way.
Once a command has been completed, and the thread is waiting for the
next command, you have safe access to all the fields/properties of
the thread, including the TidNNTP component. Firing events to return
the results, status, progress or errors is fairly easy by posting a
message to a component - maybee a configuration form that is normally
hidden, and calling assigned event handlers in the usual way. You
could simply post the message to the main form & act on it directly.
One little issue is aborting operations/commands. Often, setting an
'abort' flag that is checked in the 'onWork' event will do, but
quicker response is usually possible by forcing a disconnect.
I don't use NNTP but I don't see it as much more difficult that HTTP
or plain TCP.
Rgds,
Martin
Thanks. I'll do that. :)
- Tristan
Grahame
Tristan Bendixen wrote:
> I've been playing around with the Indy package for a while, and I'm using
> the TIdNNTP component, but it steals a lot of the Application's "interface
> time" (not sure what it's called).. Basically, the interface tends to freeze
> up while an article is downloaded..
>
> This makes me wonder, cuz quite frankly, it can't be right that I have to go
> through the huge fuss of learning and implementing threads into the
> software, just to download from an NNTP server?
>
> And just in case I have to, does someone know how? Cuz from my small level
> of experience with threads, I've found that you get errors if you try to
> access it from outside the thread, or from another thread, and I'd need full
> access to the TIdNNTP component, or something like that.
>
> Anyway, I'm hoping someone here will reply with some useful information,
> since I haven't had too much luck getting replies in here before.
>
> - Tristan
>
>
I'd think so. I've placed a TIdAntiFreeze on both of the forms that contains
a TIdNNTP component. Doesn't change anything, as it doesn't time out.
Instead it freezes when fetching a rather long message from the server.
- Tristan
Okay, made an attempt at utilizing a thread, wrapping the TIdNNTP component
in the thread, but it fails still.. In fact, now it's even worse than
before.
It used to freeze the interface while downloading an article or article list
from the TIdNNTP component, but now it just freezes up period. It doesn't
seem to do anything at all, it just stands there, doing nothing. It's really
frustrating.. :(
- Tristan
1) Only use one per app.
2) Adjust teh properties in AntiFreeze to give it more time.
--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"
Want more Indy stuff? Try the Atozed Indy Portal at
http://www.atozedsoftware.com/
* More Free Demos
* Free Articles
* Extra Support
ELKNews - Get your free copy at http://www.atozedsoftware.com
> And just in case I have to, does someone know how? Cuz from my small
level
> of experience with threads, I've found that you get errors if you try
to
[SNIP]
> Anyway, I'm hoping someone here will reply with some useful
information,
> since I haven't had too much luck getting replies in here before.
You might want to look at Colin Wilson's XANANews - it's a free, open
source newsreader that is multi-threaded. The source might be helpful to
you.
You can find XANANews at http://www.wilsonc.demon.co.uk
And if you're not getting replies to your questions here, you possibly
should look at the level of information you're providing in your
questions - I find that most of the posts that don't get a response
don't provide enough info to present the problem. :-)
Ken
---
Ken White
kwh...@adpsi.com
Clipper Functions for Delphi and C++ Builder
http://www.adpsi.com
When I'm posting a question, I'm giving as much information with it as I
possibly can. It's kinda hard to give more info than you can provide.
- Tristan
Can you perhaps post your thread code or some simple cut-down version
that desn't work? All the Indy components I've used work well in
threads. Meanwhile, I'll look a t TidNNTP & see if I can get
anything working.
Rgds,
Martin
"Tristan Bendixen" <ang...@dkfurs.dk> wrote in message
news:3df9eb8a$1...@newsgroups.borland.com...
Tristan,
FWIW, I think that threads are the way to go with Indy components. I only
use the AntiFreeze components on the simplest of applications; I don't think
it is suitable for production quality code.
In principle, when moving to threads, you isolate the your indy code from
your
GUI code, and place that in the thread. I'll try to illustrate with the
TIdHTTP
component as I have never used the TIdNNTP.
Firstly, decide what need to be accomplished: in this case I'm wat to grab
the
html code for a given URL into a given file. If I was doing this without
threads,
I'd drop a TIdHTTP component on the form and make a function like this (note
threads would be better than the stringlist):
procedure GetHTML(const AURL: string; const AFileName: string);
var
sl: TStringList;
begin
sl:=TStringList.create;
sl.text:=IdHTTP1.Get(AUrl);
sl.savetofile(AFileName);
sl.free;
end;
The problem with this is that the IdHTTP component stops this being used mor
than
once at at a time. So do the same thing, but create the http at run time:
procedure GetHTML(const AURL: string; const AFileName: string);
var
sl: TStringList;
HTTP: TIdHTTP;
begin
sl:=TStringList.create;
HTTP:=TIdHTTP.create(nil);
sl.text:=HTTP.Get(AUrl);
sl.savetofile(AFileName);
sl.free;
HTTP.free;
end;
Voila a standalone GetHTML function.
Now create a thread (File|new|thread object) call it THTTPGetter as
save as HTTPGetterU.pas
Add variables and properties so the declaration looks like:
type
THTTPGetter = class(TThread)
private
{ Private declarations }
FURL: string;
FFileName: string;
procedure SetFileName(const Value: string);
procedure SetURL(const Value: string);
protected
procedure Execute; override;
public
property URL: string read FURL write SetURL;
property FileName: string read FFileName write SetFileName;
end;
In the main unit, add this unit to the uses clause then create a button
click
handler that looks like this:
Feel free to post code here. I've written a multithreaded newsreader so
I've garnered enough experience that I can probably be of some assistance.
--
"So what are we going to do tonight, Jake?"
"Same thing we do every night, Jake's Super Newsreader. TRY TO TAKE OVER THE
WORLD!"
Lower it. There are also some boolean properties you can adjust.
> Also, reading the help, I tried figuring out what the OnlyWhenIdle
> property does, but I found the description a tad confusing. From what I
Set it to False.
> understood there, the standard setting of True, will make the AntiFreeze
> work only when the main thread isn't doing anything, and that doesn't
> really make sense.. Maybe I'm just a bit slow today, but still.. Could
> you explain it, or atleast attempt to? :)
It has no effect on threads.
--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"
Want to keep up to date with Indy?
Join Indy News - it free!
http://www.atozedsoftware.com/indy/news/
oops clicked too soon ...
procedure TForm1.Button1Click(Sender: TObject);
const
fn : integer = 1;
var
Thrd: THTTPGetter;
begin
inc(fn);
Thrd:=THTTPGetter.create(true);
with Thrd do begin
Thrd.FreeOnTerminate:=true;
URL:='http://borland.com/';
FileName:='c:\00'+inttostr(fn)+'.txt';
resume;
end;
end;
and move the GetHTML function into the thread execute function:
procedure THTTPGetter.Execute;
var
sl: TStringList;
HTTP: TIdHTTP;
begin
sl:=TStringList.create;
HTTP:=TIdHTTP.create(nil);
try
sl.text:=HTTP.Get(FURL);
sl.savetofile(FFileName);
finally
sl.free;
HTTP.free;
end;
end;
Note I have added the try finally's.
Now for every click on the button a new thread starts and a new file
is created (when the Get(url) returns.
HTH
Mike
U don't have to fuss :-)
...just drop aTidAntiFreeze component on your form. This will call a
ProcessMessages enough times to allow your user to interface with the GUI.
Thats the easy ay - the slughtly more involved way (but, imho better for
this type of thing)
is to create a simple thread that incorporates the NTTP client - this gives
you total
control over the client and you can signal back and forth to the thread at
will.
/A.
Cool! That worked like a charm! Thanks. :o)
I can't wait to see the finished version of Indy 10 (I'm waiting with the
install till it's up to an official release).
- Tristan