Indy TIdHTTP worker events [Edit]

I'm using the Indy tIdHTTP component on a form and have defined the OnWorkBegin, OnWork, OnWorkEnd events
I've used this code in C++Builder XE2 and Indy 10.5.8.0. and it worked just fine but in XE8, Indy 10.6.2.5263. all the 'worker' events are fired when IdHTTP1->Get(URL, pFStream)
is completed. All Events are "piled up" and fired sequentially after Get() is completed.

{code}
{
.....
FileName = fl.GetFolderPath(&FOLDERID_InternetCache) + "myfile.exe";
pFStream = new TFileStream(FileName, fmCreate);
IdHTTP1->Get(URL, pFStream);
delete pFStream;
....
}

void __fastcall TFormSettings::IdHTTP1WorkBegin(TObject *ASender, TWorkMode AWorkMode,  __int64 AWorkCountMax)
{
	ProgressBar1->Max = AWorkCountMax;
	ProgressBar1->Position = 0;
	ProgressBar1->Visible = true;
	LabelDownload->Visible = true;
	Update();
}

void __fastcall TFormSettings::IdHTTP1Work(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount)
{
	ProgressBar1->Position = AWorkCount;
	Update();
}

void __fastcall TFormSettings::IdHTTP1WorkEnd(TObject *ASender, TWorkMode AWorkMode)
{
	ProgressBar1->Visible = false;
	LabelDownload->Visible = false;
}
{code}

What can be the cause of this behaviour?
I'm running just 1 thread.

Thanks in advance,
René

Edited by: rene v.d. berge on Jul 28, 2015 7:22 AM

Edited by: rene v.d. berge on Jul 28, 2015 7:23 AM
0
rene
7/28/2015 2:24:21 PM
embarcadero.cppbuilder.socket 566 articles. 0 followers. Follow

3 Replies
826 Views

Similar Articles

[PageSpeed] 22

rene wrote:

> I've used this code in C++Builder XE2 and Indy 10.5.8.0. and it
> worked just fine but in XE8, Indy 10.6.2.5263. all the 'worker'
> events are fired when IdHTTP1->Get(URL, pFStream) is completed.

That is physically impossible, in any version of Indy, as the OnWork... events 
are triggered inside of Get() itself while it is reading/writing blocks of 
data.  It is not possible for the events to trigger after Get() has exited. 
 What is actually happening is that your UI updates are getting backed up 
instead, not that the OnWork... events are getting backed up.

> All Events are "piled up" and fired sequentially after Get() is completed.

The events are triggered in the same thread context that is calling TIdHTTP.Get(). 
 If you are calling Get() in the main UI thread, it is going to block the 
main message loop from processing new messages, unless you have a TIdAntiFreeze 
component on the Form.  What you are seeing happen is your UI updates are 
getting stuck in the message queue and not being processed until after Get() 
has exited and returned control to the main message loop.  You are calling 
the Form's Update() method, but all that is going to do is process pending 
paint messages, not all pending messages.  A themed progress bar, for instance, 
runs a timer internally to update its drawing state smoothly, and Update() 
will not process/dispatch those timer messages, but TIdAntiFreeze would.

> pFStream = new TFileStream(FileName, fmCreate);
> IdHTTP1->Get(URL, pFStream);
> delete pFStream;

FYI, if Get() fails, an exception is raised, which you are not catching, 
so you would leak the TFileStream object and its associated file handle. 
 You need to add an exception handler:

{code}
pFStream = new TFileStream(FileName, fmCreate);
try
{
    try
    {
        IdHTTP1->Get(URL, pFStream);
    }
    __finally
    {
        delete pFStream;
    }
}
catch(const Exception&)
{
    DeleteFile(FileName);
    //...
}
{code}

> void __fastcall TFormSettings::IdHTTP1WorkBegin(TObject *ASender,
> TWorkMode AWorkMode,  __int64 AWorkCountMax)
> {
> ProgressBar1->Max = AWorkCountMax;

Keep in mind that:

1. AWorkCountMax will be 0 if TIdHTTP does not know the size of the file 
being sent, either because the data is being sent using the "chunked" transfer 
encoding, or because the server ends the file by closing the socket.

2. You should check the AWorkMode parameter and only do your logic if the 
mode is wmRead and not wmWrite.

> void __fastcall TFormSettings::IdHTTP1Work(TObject *ASender, TWorkMode
> AWorkMode, __int64 AWorkCount)
> {
> ProgressBar1->Position = AWorkCount;

If the Max is set to 0, setting the Position is useless.  Also, same thing 
about checking the AWorkMode parameter.

> What can be the cause of this behaviour?
> I'm running just 1 thread.

Do you mean you are running the TIdHTTP in its own worker thread?  Or in 
the main UI thread?  It makes a big difference.

If you are running TIdHTTP in the main thread, you need to either use TIdAntiFreeze 
or move TIdHTTP to a worker thread to unblock the main thread.

If you are running TIdHTTP in a worker thread, the OnWork... handlers you 
have shown are not thread-safe, you need to sync with the main thread to 
perform UI updates safely.

-- 
Remy Lebeau (TeamB)
0
Remy
7/28/2015 6:41:34 PM
Thanks Remy for your prompt response, much appreciated!

> Do you mean you are running the TIdHTTP in its own worker thread?  Or in 
> the main UI thread?  It makes a big difference.
> 
> If you are running TIdHTTP in the main thread, you need to either use TIdAntiFreeze 
> or move TIdHTTP to a worker thread to unblock the main thread.
> 
> If you are running TIdHTTP in a worker thread, the OnWork... handlers you 
> have shown are not thread-safe, you need to sync with the main thread to 
> perform UI updates safely.

Yes I'm running just the main UI thread. After I've incorporated the TIdAntiFreeze component
Window messages are beeing serviced again by my application, but a 'HTTP worker' event still isn't fired while Get() is working...

René
0
rene
7/29/2015 8:47:29 AM
rene wrote:

> Window messages are beeing serviced again by my application,
> but a 'HTTP worker' event still isn't fired while Get() is working...

And as I said, that is *physically* impossible.  The OnWork... events are 
not message-based, they are direct calls made inside the I/O functions.  
Read a block of data, call OnWork, read a block of data, call OnWork, and 
so on.  You can verify that for yourself using the debugger, or via a real-time 
logging solution, such as OutputDebugString(), CodeSite, etc.

-- 
Remy Lebeau (TeamB)
0
Remy
7/29/2015 5:19:26 PM
Reply:

Similar Artilces:

[D2010] Indy Sockets [Edit]
Hi all! I'm new to Indy and I would like to develop my first application with TCP sockets. Anyway I'm having great problems with Indy because I really can't find a good guide. To say the truth I searched on google, yahoo and youtube. The easiest tutorial I've found is a C++ tutorial that uses Indy (on youtube). However I don't know C++ and I want to use it in Delphi. Can you show me a snippet of code that sends a string and explain it step to step? Can you give me a link to a guide that shows how to use Indy TCP clients and servers and explains how and why do these wor...

Indy Server Socket Freezing [Edit]
Hi all, how are you ? I have a little doubt, when I have connected clients and i try to put more ports to listen or close listening ports the form is freezing. For add ports {code} If IDS_Server.Active Then IDS_Server.Active := False; With tBindings.Add Do Begin IP := '127.0.0.1'; Port := StrToInt(TXT_Port.Text); End; IDS_Server.Bindings := tBindings; IDS_Server.Active := True; LB_Ports.Items.Add(TXT_Puerto.Text); {code} For close ports {code} If IDS_Server.Active Then IDS_Server.Active := False; If tBindings.Count =...

Re: [D2010] Indy Sockets [Edit]
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message news:... > TSimpleClient = class(TIdContext) Minor correction: {code:delphi} TSimpleClient = class(TIdServerContext) {code} -- Remy Lebeau (TeamB) ...

Can Indy TIdHttp connect to Google.com with SSL ? [Edit]
Hi All, I am using Delphi 5 + TIdHttp (Indy 9) , In my experience and test, They work well with Google + SSL before 2009/8. After Google seem upgraded its SSL that time, i found they cant work with Google+SSL anymore. Can anyone connect to Google with SSL well? -- Chen Chi-Shun(陳基順), http://groups.google.com/group/chi-shun-chen Software Developer: Developing Rss/Twitter Cleint-Reader. Forex Trader and WarCraft III player. Edited by: Andrew Chen on Feb 25, 2010 7:35 PM ...

Indy 10 TIdHTTP, TIdLogStream and access violation error [Edit]
cleared Cleared by: Adamski Sławomir on Dec 5, 2013 10:21 AM ...

TIdHTTP, TIdSSLIOHandlerSocketOpenSSL, Socket Error # 10060, Connection tim [Edit]
hi! I need help {code} {uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdMultipartFormData, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL, IdExplicitTLSClientServerBase, IdMessageClient, IdIMAP4;} {openssl-1.0.1e-i386-win32.zip libeay32.dll ssleay32.dll в корневой папке } procedure TForm1.Button1Click(Sender: TObject); var data : TIdMultiPartFormDataStream; idhp: TIdHTTP; IdSSL: TIdSSLIOHandlerSocketOpenSSL; begin idh...

CB2010 Indy 10
CB2010 Indy 10 I am using the TIdIOHandlerSocket::Write method. I'm trying to send an AnsiString which contains the following data: "ÓëÐ™" what is actually sent is: "OeDiSRT" Note that they look similar, but the binary data is different. I am doing some migrations from BCB6 to CB2010, and before the TIdIOHandlerSocket::Write method would write the same binary data as was in the AnsiString. Now it appears to do some conversion before sending? Can anyone shed some light on this and offer advise on how I should be writing t...

aborting a new event/edit event dialog
[In case this matters, I'm using Lightning + WCAP.] Currently when you use new event / edit event, you are presented with a dialog box with no way out. The only button is "Save". There needs to be a "Cancel" button. I finally realized that the escape key can be used. But if you're doing a GUI interface, there should be buttons for all functions. Hi, the (prototypical) wcap event dialog has been reworked completely, so I think you should check the latest nightly (IIRC Mickey checked it in yesterday). It still does not have cancel, but is modeless. Don...

Is it allowed to call Indy component from Indy worker threads?
Hi! I have a chain of Indy components that implements a *My FTP Client 1* <--> *My FTP Server* <---> *My FTP Client 2* <--> +(External FTP server)+ Now, the chain *Client1 -- Server -- Client 2* lives within the same application. And the *Server -- Client2* is to behave like proxy for the external server. My problem is to make the Client 1, server, Client 2 chain to work without error. But so far it does not. Sometimes it leaves the Client2 connection to the external server hanging (Exception EIdAleradyConnected). And sometimes the whole application crashes with an a...

Editing subsequences of recurring events; Customizeable event templates
-Recurring Events Most of my scheduling is recurring events, such as classes, sections, and office hours. Every calendar program allows these to be set up, but few allow more than one instance to be modified without changing the entire event. Calendarscope does, but it has other failings in areas where Sunbird shines. To illustrate what I mean: Last quarter I had to change my office hours mid-quarter. I wanted to update my calendar to reflect this. I could change the entire event, which would change the time on all of them, including the ones that did occur at the original time. I c...

Indy Sockets.
Is it OK to ask an Indy Socket question here ? If not where can I ask it ? > {quote:title=Tony Blomfield wrote:}{quote} > Is it OK to ask an Indy Socket question here ? If not where can I ask it ? It is better to use the WinSock subforum in the Delphi category. ...

Indy or Sockets
Hi, I'm triying to make a simple chat service application, and want to know wich one is better, ServerSocket or Indy components? Wich one can give me the best speed of acess, data loss, connection type, best service? Or if there are others that can give the best way to implement the server and client the most easy way, or any link or examples of how to use, if someone know anyone, can please help me? one more thing, wich one is better TCP or UDP? and are any more types better for what I want? thks ...

How GridView1_RowEditing event determines the commandName of edit button which is set to Edit
How GridView1_RowEditing event determines the commandName of edit button which is set to Edit? How GridView1_RowUpdating determines the commandName of edit button which is set to Update?-----------------------------------------------Please click Mark as Answer if this helped. The GridView has a method called HandleEvent that looks at the CommandName and determine which event to process.  The CommandNames (Edit/Update/Cancel/Delete/Sort/Select/Page) are hardcoded in that method. Hope that helps. AaronDon't forget to click "Mark as Answer" on the post that helped ...

To edit or no to edit
Jon, Can I edit, whatever I've written so far, so that it doesn't look like I wrote utterly crap?-) -- Pieter "Linux is like living in a teepee. No Windows, no Gates, Apache in house." -- Usenet signature Pieter Zijlstra wrote: > Jon, > > Can I edit, whatever I've written so far, so that it doesn't look like > I wrote utterly crap?-) Oh boy, the edit button vanished from the web-forum ... ;-) -- Pieter "Humor is also a way of saying something serious." -- T. S. Eliot (1888 - 1965) Pieter Zijlstra wrote: ...

Web resources about - Indy TIdHTTP worker events [Edit] - embarcadero.cppbuilder.socket

Resources last updated: 11/23/2015 8:46:31 AM