Skip to Content
0
Jul 30, 2016 at 09:32 AM

PowerBuilder spontaneously starting a new Thread

410 Views

Hello All,

First of all, I would like to clear out that we are not using Multi-Threading in PowerBuilder anywhere in our application. We are using PowerBuilder 11.5 Classic Build 4740. We have a report window with a "Retrieve" toolbar menu item. Now when a user clicks on "Retrieve" we call an event on the same window to do some processing and then call dw_main.Retrieve() to retrieve the data. Now as this is a single threaded application the Stack Pointer should stay at dw_main.Retrieve() until the retrieve is complete. Now this report takes around 5 minutes to retrieve. While we are at the dw_main.Retrieve() line, if the user clicks the "Retrieve" toolbar item again, the menu gets clicked. It even calls the window event which is triggered from the menu and dw_main.Retrieve() gets called again which in turn results in the following error:

Select Error: Only the cancel command is allowed when the rows are pending.

So this just proves that the dw_main.Retrieve() was called again. I don't see any way this could happen in a single threaded application as we were still at the dw_main.Retrieve() (OR in some other events like retrievestart,retrieveend,retrieverow which get fired during Retrieve, but is not important here as it should not execute the click of the menu until the whole Retrive() process is complete). Now the workaround solution to this is easy as we can just disable the "Retrieve" menu item, but I just gave this example as I can replicate it every time.

Now the same issue is happening in our other core logic which is creating Concurrency issues. Please find below the skeleton of the code.

For ll_loop = 1 to ll_loop_end
     /*
     le_id = Some code to get the primary key of a row in a table
     ls_filename = some code to create a unique file name for each iteration which also contains value of le_id its name
     */
    
     //retrieve the data in a format defined in datawindow to create its PDF
     ids_datastore.Retrieve(le_id)

     //create a PDF file
     If ids_datastore.SaveAs(ls_filename, PDF!, False) = -1 Then
          /* Some error handling code */
          Return -1
     End If

     //Update the created document's path in the table
     UPDATE TABLE_NAME
          SET DOC_PATH = :ls_filename
     WHERE
          TRAN_ID = :le_id;

     /*
     some code to check for database errors
     */
    
Next

Now this is what happened, the loop was running for 10 times. during the 2nd iteration, it got stuck in SaveAs, but somehow it just skipped the second iteration and started 3rd iteration and completed all the 10 iterations. After completing the 10th iteration, it resumed the 2nd iteration, so the PDF of 2nd iteration got generated and then it went to execute the embedded SQL statement. Now the le_id variable was containing the value corresponding to the 10th iteration, so the PDF of 2nd iteration got saved in the row corresponding to 10th iteration.

Now the 2nd scenario is hard to replicate, but I came to this conclusion on the following basis:

1. The PDF that was generated in the 2nd iteration was scrambled, so we know something went wrong there.

2. I can see the PDF creation date in windows which confirms that the PDF of 2nd iteration was created after all the PDFs were created.

3. We have database logs which also confirms the same exact flow as described above.

Has anyone ever encountered this kind of problems? I would really like if some can shed some light on how this could happen in a single threaded application?