[DUG] Program crashes - anyone knows why?

Matthew Comb matt at ferndigital.com
Mon Nov 27 12:14:39 NZDT 2006


Hi.

Just a couple of things I noticed.

You are creating your critical section within your worker thread. This
won't protect anything as all of your worker threads will have their own
instance of the critical section.

You are creating your critical section to access a boolean ? This is not
needed as you cannot have a conflict on a boolean type.

Are any of your worker threads passed the same file name ? This for sure
would cause a problem.

Matt.



> On Sun, 26 Nov 2006 23:16:50 +0100, Matthew Comb <matt at ferndigital.com>
> wrote:
>
>> Sorry if Im stating the obvious.
>
> No problem Matt it is usually the most obvious things that go wrong ;)
>
>> Have you suspended your threads before assigning any of their properties
>> ?
>> This can cause problems.
>
> Hmmm yeah I create each thread as
>
> thread := QueryThread.Create(true);  // true = start suspended
>
> I think that should do it, right?
>
>> What does your thread execute do aside from update the GUI in your syn
>> routine? Does it access anything else application wide? or any local
>> files?
>
> It accesses the two lists which are global. But they are TThreadLists so I
> shouldn't be doing any synchronization.
> Each thread accesses the GetInetFile method alot, so this can be the weak
> point of the application. But I cannot synchronize this method, because
> the point of the threads is to make the downloading faster. If each thread
> had to wait for another to finish downloading a page from the internet
> then there would be no point for using threads.
>
> I've read about the WinAPI functions I'm using in this method and they are
> all thread safe, according to MSDN.
>
> Here's the method itself. I'll explain the relevant parts in comments.
>
> var
>    ENABLE_CACHING: boolean;  // global variable
>
> function GetInetFile(const fileURL, FileName: String; proxy:
> TProxyAddress): boolean;
> const BufferSize = 1024;
> var
>    hSession, hURL: HInternet;
>    Buffer: array[1..BufferSize] of Byte;
>    BufferLen: DWORD;
>    f: File;
>    sAppName,error: string;
>    caching: boolean;
>    critical: _RTL_CRITICAL_SECTION;   // used for critical section
> begin
>   Result := False;
>
>   InitializeCriticalSection(critical);  // here I am accessing the
> ENABLE_CACHING
>   EnterCriticalSection(critical);       // global variable, so I use a
> critical
>   caching := ENABLE_CACHING;            // section for synchronizing
>   LeaveCriticalSection(critical);
>   DeleteCriticalSection(critical);
>
>   error := '';
>   sAppName := ExtractFileName(Application.ExeName);
>
>   if proxy = nil then
>     hSession := InternetOpen(PChar(sAppName),  // this function starts the
> session
>                  INTERNET_OPEN_TYPE_PRECONFIG, // it should be thread-safe
>                 nil, nil, 0)
>   else
>     hSession := InternetOpen(PChar(sAppName),  // configure to use a proxy
>                  INTERNET_OPEN_TYPE_PROXY,
>                  PChar(proxy^.host + ':' + IntToStr(proxy^.port)), nil,
> 0);
>
>   if hSession = nil then        // this is for debugging
>     error := 'Unable to open Internet connection.';
>
>   try
>     if caching then
>      hURL := InternetOpenURL(hSession,  // check if URL exists
>              PChar(fileURL),            // this should be thread-safe
>              nil,0,0,0)
>     else     // caching disabled
>      hURL := InternetOpenURL(hSession,
>              PChar(fileURL),
>              nil,0,INTERNET_FLAG_RELOAD,0);
>
>    if hURL = nil then
>      error := 'Unable to open URL: ' + fileURL;
>
>    try                // now I open a new file and write the content into
> it
>     AssignFile(f, FileName);
>     Rewrite(f,1);
>     repeat
>        // download file from the internet, this should be thread-safe
>        if not InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen)
> then begin
>          error := 'Error reading from file: ' + fileURL + #13'Maybe your
> proxy is not working?';
>          break
>        end;
>        BlockWrite(f, Buffer, BufferLen)
>     until BufferLen = 0;
>     CloseFile(f);
>     Result:=True;
>    finally
>     InternetCloseHandle(hURL)
>    end;
>   finally
>    InternetCloseHandle(hSession)
>   end;
>
>   {$IFDEF Debug}
>   if error <> '' then
>     raise Exception.Create(error)
>   {$ENDIF}
> end;
>
> In any case, this method is inside a try-except block. So if anything goes
> wrong I will catch the exception.
>
>
>> Are you using Indy for your sockets? (These are components not classes)
>>
>> Are you using an activex controls ?
>
>
> No I'm not using any custom components or libraries, most of the stuff is
> by me or I've found it on the internet (like the GetInetFile method, which
> is from http://delphi.about.com/od/internetintranet/l/aa013001a.htm ). I'm
> trying to use the WinAPI whenever I can, I find it to be more reliable
> than custom components.
>
> The client still hasn't replied (he's from Canada so it's probably still
> Sunday afternoon there :)). I've placed everything in the Execute method
> into a try-except block, hopefully that will do it.
> If not I'll try one of the debug libraries suggested by you guys.
>
> Thanks for the help,
> Csaba
>
> _______________________________________________
> Delphi mailing list
> Delphi at ns3.123.co.nz
> http://ns3.123.co.nz/mailman/listinfo/delphi
>




More information about the Delphi mailing list