Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Threads

38 views
Skip to first unread message

Håkon Clausen

unread,
Jul 31, 2002, 5:33:42 AM7/31/02
to
Hi,

I'm trying to make my app getting a report via http. Since the
oHTTP:GetRespons() is taking some time, I'm trying to do this in a thread. I
have several problems with it. First of all it is very unstable,
particularly if I launch several thread at a time. Does someone have some
debugging tip on how to debug thread in general?

One other thing I'm having problems with is how to exit the thread. From
white papers and other posts to this NG it should do with just return, or
maybe ExitThread. Non of this works for me. When the thread function comes
to this, it just hang the whole app, using 100% of the cpu. The only thing
that works is if I'm using TerminateThread(GetCurrentThread())?

Some of my code (first the method that fires the thread, an then the thread
function)

Håkon

METHOD RunReport(oFlagWin AS FlagWindow, nReportId AS INT) AS VOID STRICT
CLASS ReportManager
LOCAL oReport AS Report
LOCAL dwThreadID AS DWORD
LOCAL oProgressDialog AS ProgressDialog
LOCAL pThread AS PTR
LOCAL dwReport AS params

~"ONEARLY+"
? cUrl
oProgressDialog := ProgressDialog{NIL, cReportName}
oProgressDialog:Show()

cReportServerName := SELF:oProject:AppData:ReportServerName
oReport := Report{cUrl, oProgressDialog:Handle(), cReportServerName,
cReportName}
oProgressDialog:Report := oReport

dwReport := MemAlloc(_SizeOf(params))
RegisterKid(dwReport,2,FALSE)

dwReport.report := PTR(_CAST, oReport)
pThread := CreateVOThread(NULL_PTR, 0, @NewReportHTTPThread(), dwReport, 0,
@dwThreadId)
oProgressDialog:ThreadHandle := pThread
CloseHandle(pThread)
~"ONEARLY-"

FUNCTION NewReportHTTPThread(dwParam AS DWORD) AS DWORD PASCAL
LOCAL pHandle AS PTR
LOCAL oReport AS Report
LOCAL oHTTP AS cHTTP
LOCAL cTmp, cHTTPCode AS STRING
LOCAL nStart, nEnd AS INT
LOCAL s AS params

s := dwParam
oReport := OBJECT(_CAST, s.report)
pHandle := oReport:ProgressWindowHandle

/** OPEN **/
VOSendMessage(pHandle, REPORT_ADD_STATUS, 10, 0)
oHttp := cHttp{}
IF !oHttp:Open()
VOSendMessage(pHandle, REPORT_ADD_STATUS, 11, 0)
RETURN 0
ENDIF

/** CONNECT **/
VOSendMessage(pHandle, REPORT_ADD_STATUS, 20, 0)
IF !oHttp:ConnectRemote(oReport:ServerName)
VOSendMessage(pHandle, REPORT_ADD_STATUS, 21, 0)
RETURN 0
ENDIF

/** OPEN REQUEST **/
IF !oHttp:OpenRequest("GET", oReport:Url, 0)
VOSendMessage(pHandle, REPORT_ADD_STATUS, 31, 0)
RETURN 0
ENDIF

/** SEND REQUEST **/
VOSendMessage(pHandle, REPORT_ADD_STATUS, 40, 0)
IF !oHttp:SendRequest(NULL_STRING,NULL_PTR,0)
VOSendMessage(pHandle, REPORT_ADD_STATUS, 41, 0)
RETURN 0
ENDIF

/** GET HEADER **/
cTmp := oHttp:GetResponseHeader()
cHTTPCode := SubStr(cTmp, 10, 3)
IF !StrEquals(cHTTPCode, "200")
IF StrEquals(cHTTPCode, "404")
VOSendMessage(pHandle, REPORT_ADD_STATUS, 404, 0)
ELSEIF StrEquals(cHTTPCode, "403")
VOSendMessage(pHandle, REPORT_ADD_STATUS, 403, 0)
ELSE
VOSendMessage(pHandle, REPORT_ADD_STATUS, Val(cHTTPCode), 0)
ENDIF
RETURN 0
ENDIF
? "GetRespons..."
/** GET RESPONSE **/
VOSendMessage(pHandle, REPORT_ADD_STATUS, 50, 0)
cTmp := oHttp:GetResponse()
// get the filename:
? "done GetResponse.."
nStart := At("<file>", cTmp) + 6
nEnd := At("</file>", cTmp)
IF nEnd > nStart
oReport:FileName := SubStr(cTmp, nStart, (nEnd-nStart))
ENDIF

/** CLOSE CONNECTIONS **/
? oHTTP:CloseRequest()
? oHTTP:CloseRemote()

/** DONE **/
VOSendMessage(pHandle, REPORT_ADD_STATUS, 99, 0)
TerminateThread(GetCurrentThread(), 0)

RETURN 1

STRUCTURE params
MEMBER report AS PTR


Ginny Caughey

unread,
Jul 31, 2002, 10:10:04 AM7/31/02
to
Håkon,

You should not need to call TerminateThread. Just returning from the threaded
function should be sufficient. For starters, change the calls to VOSendMessage
to just PostMessage. You don't need RegisterKid(dwReport) because dwReport is
MemAlloc'ed in static memory anyway. I'd also suggest NOT passing a pointer to
oReport to the thread and casting it back to an object inside the thread. I know
that one of the VO samples shows this technique, but I do not recommend it. But
the main thing is, I don't understand what the rest of your app is supposed to
be doing while you're getting the report data. I'm not convinced that threading
is a good solution here - it looks like it just complicates things.

HTH,

Ginny

"Håkon Clausen" <haakon....@nosyko.no> wrote in message
news:W9O19.4553$sR2....@news4.ulv.nextra.no...

Håkon Clausen

unread,
Jul 31, 2002, 10:31:15 AM7/31/02
to

"Ginny Caughey" <ginny....@wasteworks.com> wrote in message
news:ai8r2g$12a19j$1...@ID-144704.news.dfncis.de...

> Håkon,
>
> You should not need to call TerminateThread. Just returning from the
threaded
> function should be sufficient.

That was what I thought to, but as I said, the app just hangs and the thread
is not dead. I can see that in a "taskmanager".
Any idea why the thread don't quit?

>For starters, change the calls to VOSendMessage
> to just PostMessage.

I will try this.

>You don't need RegisterKid(dwReport) because dwReport is
> MemAlloc'ed in static memory anyway.

Thanks, I was a little bit unsure about that


> I'd also suggest NOT passing a pointer to
> oReport to the thread and casting it back to an object inside the thread.
I know
> that one of the VO samples shows this technique, but I do not recommend
it.

Ok, but how should I pass a string to the thread and back? I need to give
the thread the url to get the reasons from, and I need to get the response
back (an url to the generated report) back from the thread.

>But the main thing is, I don't understand what the rest of your app is
supposed to
> be doing while you're getting the report data. I'm not convinced that
threading
> is a good solution here - it looks like it just complicates things.
>

What I'm trying to do is this. I have a report server that generates report
for me when I send a HTTP requests. This server takes data from the SQL
server, makes XML out of it, pass it to a FOP server that takes the XML and
a XSL document an output a report in a chosen format (e.g PDF) This process
takes a little bit of time (1 min perhaps, even more if the report get big).
The server returns an url to where I can find the generated report. When I
send a oHTTP:GetRespons(), the process hangs (e.g. 1 min) to the response
has been received. I'm like to do this in a thread so that the user can do
other things here, so I can show a nice animation while he waits etc, ask
for more reports etc. I thought that this was the ideal situation to use
thread. I have also considered to do it in another process, but the IPC is
then a little more tricky. Do you have any suggestions of how I can do this
in another way?

Regards
Håkon

Ginny Caughey

unread,
Jul 31, 2002, 11:12:13 AM7/31/02
to
> Ok, but how should I pass a string to the thread and back? I need to give
> the thread the url to get the reasons from, and I need to get the response
> back (an url to the generated report) back from the thread.

I'd probaby use PSZs to avoid sharing dynamic memory between threads. I don't
know if that is strictly necessary, but that approach does yield reliable
threaded code in VO. You could try a regular VO string for the urls and see if
that causes problems as an alternative before going with PSZs. I just don't know
for sure how good the GC is with multiple threads in the current version of VO.
(Before 2.5, it definitely wouldn't work.)

> What I'm trying to do is this. I have a report server that generates report
> for me when I send a HTTP requests. This server takes data from the SQL
> server, makes XML out of it, pass it to a FOP server that takes the XML and
> a XSL document an output a report in a chosen format (e.g PDF) This process
> takes a little bit of time (1 min perhaps, even more if the report get big).
> The server returns an url to where I can find the generated report. When I
> send a oHTTP:GetRespons(), the process hangs (e.g. 1 min) to the response
> has been received. I'm like to do this in a thread so that the user can do
> other things here, so I can show a nice animation while he waits etc, ask
> for more reports etc. I thought that this was the ideal situation to use
> thread. I have also considered to do it in another process, but the IPC is
> then a little more tricky. Do you have any suggestions of how I can do this
> in another way?

Yes, I do agree that waiting for HTTP:GetResponse is a good place for a thread
just to keep the GUI responsive. One approach would be to have your main thread
do all the work right up until the HTTP:GetResponse call. Use a worker thread to
do that call, and have the main thread maybe loop with calls to
ApplicationExec(EXECWHILEEVENT) and Sleep(100) or whatever inside the loop until
the worker as finished. You might want to also check inside the loop to see if a
user pressed the Cancel button on the GUI. You also might not want to wait
infinitely for HTTP:Response to return since it's possible that might not happen
due to network problems, etc. If you time out, you need a way to signal the
worker thread to return. I guess if HTTP:Response is a blocking call, you'd have
to kill the worker thread from the main thread. Is there a non-blocking from of
HTTP:Response? That would be ideal - then you could tell the worker thread to
abort itself.

Ginny


0 new messages