I was recently debugging a fairly large chunk of actionscript 3 code that was in an AIR app. I had posted about some problems I was having with async file routines where basically I would have a bunch of file i/o pending it the application would appear to freeze or stall and the event handler for some of the file calls would never trigger.
After lots of debugging and testing, I believe I have identified the problem. First let me explain that I am fairly new to AS3 and Flex in general. I have been programming for nearly 3 decades so I’ve seen it all! I used to do a lot of OS-level systems programming in assembly, C++ and 20+ years of application and web programming. When I took on this as3 project I hacked out some solutions to problems without fully groking how as3 works under the hood. As a systems level programmer myself, I was intrigued by the nature of some of the bugs I saw and did some deep digging into the inner sanctum. To make a long story shorter, I believe it was failure to embrace the as3 event model that did me in.
Rather than master the event handling and dispatching for my own classes, I was “lazy” and passed new classes various Function parameters in constructors (or setters). I would register for event notification for any object that REQUIRED me to do so, such as the async file calls, mouse and keyboard handling, etc. But my own code I tended to write callback functions that would be called from the event handlers upon reaching some state (such as all async IO completed).
I now believe that in doing so I effectively blocked a main thread of execution in the flash runtime vm that caused a deadlock condition. To elaborate, I can give a quick example. If you have a class that needs to load some XML and then do something else, you can easily hang flash/flex/as3 by making the call to the async loaders and then in the next line of code wait in a loop until some boolean variable is set indicating that the complete event has fired. I learned this on day one with flash. There is no “sleep” concept like in most languages. You simply can’t write code in that type of linear fashion.
Even though I knew that, I fell prey to being lazy and not building events to use to communicate major state changes in this large application. So while my event handlers for Adobe API calls (such as AIR async filestream.open) appeared to be working, because I was daisy-chaining so many activities using Function callbacks versus events my code would often freeze. I believe my lazy coding style resulted in blocking threads. Being a systems guy I would watch the thread count and try to observe the difference between cases where the app worked and when it didn’t. The key difference was when it failed there were numerous other events occurring (windows being minimized or dragged) and events were being “lost”.
I hope this makes some sense. The moral of the story is if you want to write non-trivial apps in AS3 then you better embrace the new event model. Failure to do so may result in code that works sometimes, maybe even most of the time, but it is a timebomb waiting to fail if a mission critical thread in the runtime system gets blocked for too long. After some refactoring I was able to solve my problems. Other than changing from daisy-chained Functions to a more proper event system, I made no other changes to fix my stability problems.
I must say I was pretty disappointed that there isn’t better (or ANY) documentation on how the threading model in the player/runtime works (or what makes it NOT work). If Adobe wants us to use Flex/AIR for serious production-quality RIA, we need insight into how the threading and event models work. And PLEASE ADOBE, ADD EXPLICIT THREAD SUPPORT. I’m sure I will start a holy war with this comment, but threading support is not a luxury it is a necessity.In a perfect world we could all let the runtime worry about that for us, but open you eyes… Does the world look perfect to you?