How to develop Multithreaded applications with PowerBuilder - Questions and Answers from the webinar
During this webinar, we will build multithreaded applications (with versions prior to PowerBuilder 12) so that they can be run as separate processes in order to maximize processor and memory usage. We will also explain the new features and advantages of doing multithreaded development in PowerBuilder 12.5 using PowerBuilder .NET functions.
Presenter: Bruce Armstrong
Q: Is there a way to have threads communicate with each other or does communication have to go through the main thread?
A: Communication should go through the main thread as the child threads have no knowledge of each other, just of the parent thread (the UI thread). If you want to have child threads coordinate, you can either pass the info back to the main thread or have another mechanism (e.g., data in the database) that helps them communicate.
Q: Is multithreading only appropriate for standalone background processing that doesn't interact with the user interface other than instance and global variables.
A: The child threads should not interact with the user interface directly. They can pass back information to the main (UI) thread and have the main thread display the information to the user through the user interface. The child threads should not attempt to do that directly. The child threads do not have access to instance or global variables of the main thread.
Multithreading is largely used when you do not want the main thread to be tied up waiting for the completion of an operation. It may be a long running operation or it may be a series of shorter running independent operations that you want to run concurrently rather than sequentially.
Q: If I am using multithreading to retrieve a datawindow, can I pass the datawindow as a reference?
A: You have to be careful about having multiple threads trying to access the same system resources at the same time. To ensure that your code is thread safe, you might pass in the datawindow object so that the child thread can do the retrieval and then pass the data back to the main thread. The main thread would then update the datawindow control.
Q: how does multithreaded processes return values to main thread?
A: In PowerBuilder Classic you can create a method on the shared object that takes a reference to an non visual object on the main thread. When the child thread completes, it can call a method or event on that object reference to return the data to the main thread.
In .Net there are number of similar techniques for handling this. For example, you could use ThreadPool.QueueUserWorkItem, which takes a state object as the second argument. You set the data in the state object and then use the EventWaitHandle to tell the main thread that the child thread is done.
Q: can threaded processes display messageboxes?
A: It can, but it shouldn’t. All UI interaction should be handled by the main (UI) thread.
Q: How is this different from spawning 6 exes to simulate multithreading?
A: Largely control and communication. Launching 6 exes doesn’t allow any one of the exes monitor progress or control the operation of the other exes.’
Q: Don't you have to write a full application for a thread? You must connect to database, instatiate and destroy objects, etc
A: Not a full application. It’s a self encapsulated non-visual object. You would instantiate and destroy objects in a non-visual object that you would not turn into a shared object. The main difference is that the shared object doesn’t have access to global variables (e.g., SQLCA).
Q: Yes, you can open gui objects from a thread (windows, messageboxes)
A: You can, but it’s not recommended. Note that in the .Net Framework, there are actually safeguards build into the framework to prevent any thread other than the thread that creates a UI object from interacting with it. There are no such safeguards in Win32, but that increases the potential for collisions form thread attempting to access the same visual object.
Q: How do you debug threaded code?
A: What I do is run the application again with the code in question as non shared (non multi threaded) to see if I can reproduce the problem there. The PowerBuilder IDE is only capable of debugging code in the main thread. If I am unable to reproduce the error when the code is not shared, I would add tracing logic to the shared object (e.g., writing debugging information to a file) to further pinpoint what the issue might be.
Q: Do you know of a replacement for distributed powerbuilder?
A: The closest thing I’m aware of is creating web services and calling them via web service client or web service based datawindows.
Q: is possible migrate all functionality from PB 9 to 12.5 .NET?
A: There are a number of features that are either modified in their behavior or unsupported in PowerBuilder.Net. The full list is included in the “Modified and Unsupported Features in PowerBuilder.Net” section of the PowerBuilder.Net Features Guide in the PowerBuilder documentation. (http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc01261.1250/doc/html/hfr1226005138433.html)
Q: can you send me code example. Please?
A: I’ve provided the sample code to PowerBuilder.TV, who will make it available on their web site.
Q: Can the objects be autoinstanciate?
A: They could be, but I’m not sure what that would accomplish. You still have to use SharedObjectRegister and SharedObjectGet methods to create and get a reference to the shared objects. You don’t perform a CREATE on them, which is the step you bypass by having the object autoinstantiate.
Q: and the coding is the same in powerbuilder 10.5 and also if the coding sample would work in previous versions also
A: Shared object support was added to PowerBuilder as of PowerBuilder 6.0. The techniques shown for Classic PowerBuilder work in all versions 6.0 and later.
Q: Do you have to clear the shared object register, or do the objects need to be autoinstantiate so they clean up themselves?
A: There is a SharedObjectUnregister method used to tell PowerBuilder to destroy the shared object once there are no longer any references to it. There is also a SharedObjectDirectory function that can be used to determine what objects are currently shared.
An autoinstantied object doesn’t clean itself up, it just save you from having to issue an explicit CREATE. PowerBuilder’s own garbage collection handles the DESTROY automatically for both autoinstantiated and manually created objects.
Q: Can you create a .net component and use it in PB 12.5 classic?
A: If you generate a .Net assembly from PowerBuilder.Net 12.5, you can access it from any of the .Net targets in the PowerBuilder Classic IDE just as you would any other .Net assembly.
If you generate a .Net assembly from PowerBuilder.Net 12.5 (and comply with some of the limitations of COM Callable Wrappers) you could access it from a PowerBuilder Classic target through CCW. See the article I did in January of 2001 in PBDJ for more details (http://pbdj.sys-con.com/node/1668463).
Q: How do you know if a thread ended
A: In PowerBuilder classic, you would call a method or event on the interface object that you passed in on a method of the shared object to let the main thread know that the child thread has finished.
Q: What would you get if the thread is no longer available when you call ShareObjectGet?
A: You would get either a SharedObjectCreateInstanceError! or SharedObjectNotExistError! return from the SharedObjectGet call.
Q: Do we need to define all transacton objects within a thred? or can we pass it to the thred?
A: You could pass the information needed to create the connection (connection parameters) to the thread. Passing the transaction itself could be an issue. First, PowerBuilder won’t let you pass anything other than a custom non-visual to a method in a shared object. It won’t complain when you compile the app, but you’ll get an error at runtime. You would have to wrap the transaction in a custom non-visual and pass that. If you did so, then you would have to be concerned about whether the PowerBuilder database drivers as well as the database vendors client drivers supported multithreaded access on the same connection. I attempted this with and ODBC SQL Anywhere connection, and PowerBuilder crashed quite consistently when the multiple threads attempted to use the same connection.
I’d also question what it would achieve if it did work. If the database interaction is something you’ve moved onto a separate thread in order to improve performance (running several different database operations concurrently), it would seem to defeat the purpose to have all of the separate thread then forced to use the same connection to talk to the database.
Q: Can we still allow data entry on a main window while thred is running?
A: Absolutely. That’s one of the main reasons for multi-threading: to relieve the UI thread of long running processes that would make the UI unresponsive.
Q: or saving datawindow?
A: Same as above.
Q: Is there a way to share an external object like a JAR file?
A: So long as you are attempting to read it there shouldn’t be a problem. You can start having issues if you have multiple threads attempting to change system resources (write to file, change data in memory, etc) at the same time.
Q: Are there any issues calling powerbuilder libraries from a thread with regards to thread safety?
A: As long as it’s just a read operation, you shouldn’t have problems.
Q: could you re-iterate the thread safety issue you said you mentioned earlier?
A: Perhaps some references would help. The first is on thread safety, the second on a particular form of the problem called a race condition. As long as the different threads are just reading from shared system resources, there shouldn’t be too many problems. The issues start arising when more than one thread is attempting to update shared system resources.
Thread Safety: http://en.wikipedia.org/wiki/Thread_safety
Race Conditions: http://en.wikipedia.org/wiki/Race_condition#Computing
Q: How do you handle failures a thread in the main thread?
A: Pass error information back to the UI thread via the object reference used to pass data back.
Q: In each thread how do you make sure the files does not have duplicate file names.
A: In the code samples? The name of the file to write was passed in as an argument.