12 Replies Latest reply on Apr 8, 2011 9:15 PM by ccdoss

    calllater not working as desired

    ccdoss

      I have some compute intensive code  I want to run after I transition to another state. I want the screen to update before the computations start so it'll look smooth. I read where calllater can be used to delay execution of a function. I have tried issuing a calllater(mymethod), but mymethod starts immediately, meaning there's a screen freeze until mymethod returns. How can I solve this?

        • 1. Re: calllater not working as desired
          Flex harUI Adobe Employee

          There is a pseudo-thread example on my blog.

          --

          Alex Harui

          Flex SDK Team

          Adobe System, Inc.

          http://blogs.adobe.com/aharui

          • 2. Re: calllater not working as desired
            ccdoss Level 1

            Can you please provide a link to the post? There are many, many archives. I tried searching for calllater and it returned zero results.

            • 3. Re: calllater not working as desired
              ccdoss Level 1

              Nevermind. I misread what you were saying. I was thinking "pseudo-code", not "pseudo-thread". I found the pseudo-thread example.

              • 4. Re: calllater not working as desired
                ccdoss Level 1

                I've looked at the code, and I think I understand the concept behind it, but don't know how to incorporate it into what I'm doing.

                 

                Here's what I have:

                I have a checkbox that allows a selection. The handler for that choice does two things:

                1. Changes the state, based on the selection. This state contains a datagrid for displaying information.
                2. Calls a function, mycalc(),  that performs the calculations that are displayed in the datagrid.

                 

                The function that performs the calculations takes in a couple of arguments, including an arraylist, and returns an arraylist.

                So, do I create a thread inside my checkbox handler, that has mycalc() as the function argument? What would go in for the object argument?

                 

                Here's the code in the cbhandler:

                protected function cbStrategyScanner_changeHandler (event:IndexChangeEvent):void
                {
                    var chip:ArrayCollection;
                    // TODO Auto-generated method stub
                   
                    trace (event.currentTarget.selectedItem + " " + event.currentTarget.selectedIndex + "\n");
                    if (event.currentTarget.selectedIndex == 0)
                    {
                        currentState = "State1"; //This state change gets frozen when my call to myCalc() occurs
                    }
                   
                    switch (event.currentTarget.selectedIndex)
                    {
                        case 0: //Strategy1
                            chip = Strategy.myCalc(this.Strategies); // Would this go in the thread?
                            var i:int;
                            for (i = 0; i < chip.source.length; i++)
                            {
                                acStrategy1.addItem (chip.source[i]);
                                if (chip.source[i].strike <= minstrike)
                                    minstrike = int (chip.source[i].strike) - 1;
                                if (chip.source[i].strike >= maxstrike)
                                    maxstrike = int (chip.source[i].strike) + 1;
                                if (findDate (coveredcallmonthlist, chip.source[i].expiration) < 0)
                                    coveredcallmonthlist.addItem (chip.source[i].expiration);
                            }
                            ...//remaining cases are similar

                 

                Thank you for the help.

                • 5. Re: calllater not working as desired
                  Flex harUI Adobe Employee

                  Is myCalc() going to take a really long time?  If so, it needs to be

                  rewritten to use psuedo-threads.  How to rewrite it depends on what it does.

                   

                  If it is going to take a second or two and you're ok locking up the UI but

                  you just want to see it update before you do so, then you can just call

                  myCalc via CallLater, but you may need to chain a couple of callLaters

                  together to get it to run after the frame update.  CallLater sometimes runs

                  after other code but before the screen is drawn.

                  • 6. Re: calllater not working as desired
                    ccdoss Level 1

                    Yes, myCalc() can take several seconds to process. It's an O(n^2) process.It is a nested loop, with some simple calculations and comparisons.

                    Within the nested loop, it adds an object to an arraycollection.Once finished, it returns the arraycollection.

                    So, I guess I'd like to know what to do to break it up with pseudothread or calllater.

                     

                    Here's basically what it does:

                     

                    public static function myCalc(mylist:ArrayCollection, long:Boolean):ArrayCollection
                            {
                                var stratres:ArrayCollection = new ArrayCollection ();
                                var tmpArray:Array = mylist.toArray ();
                                var i:int;
                                var j:int;
                                for (i = 0; i < tmpArray.length; i++)
                                {
                                    var myObject1:Object = tmpArray[i];
                                    if (myObject1.type.toString () == "Strat1")
                                    {
                                        var value:Number = myObject1.value;
                                        var bid1:Number = myObject1.bid;
                                        var ask1:Number = myObject1.ask;
                                        for (j = 0; j < tmpArray.length; j++)
                                        {
                                            var myObject2:Object = tmpArray[j];
                                            var value2:Number = myObject2.value;
                                            var bid2:Number = myObject2.bid;
                                            var ask2:Number = myObject2.ask;
                                            if ((value < value2) && (myObject1.type == myObject2.type))
                                            {
                                                var myobject:Object = new Object ();
                                                myobject.close = myObject1.close;
                                                // Set source information
                                                myobject.source = myObject1;
                                                myobject.sourcebid = myObject1.bid;
                                                myobject.sourceask = myObject1.ask;
                                                myobject.stock = myObject1.stock;
                                                myobject.stockname = myObject1.stockname;
                                               
                                                // Set destination information
                                                myobject.deststock = myObject2.stock;
                                                myobject.destination = myObject2;
                                                myobject.destbid = myObject2.bid;
                                                myobject.destask = myObject2.ask;
                                                if (long)
                                                {
                                                    myobject.cost = Math.round ((ask1 - bid2) * 100) / 100;
                                                   
                                                }
                                                else
                                                {
                                                    myobject.cost = Math.round ((bid1 - ask2) * 100) / 100;
                                                   
                                                }
                                                myobject.spread = mystrike2 - mystrike1;
                                                myobject.ratio = Math.round (100 * myobject.spread / myobject.cost) / 100;
                                                myobject.maxprofit = Math.round((myobject.spread - myobject.cost)*100)/100;
                                                myobject.type = myObject1.type;
                                                myobject.selected = false;
                                                myobject.quantity = 0;
                                                stratres.addItem (myobject);
                                            }
                                        }
                                    }
                                }
                               return stratres;
                            }

                     

                    I have other myCalcs that are triple loop nests, but I think if I see how to do this, I can go to the next one.

                    • 7. Re: calllater not working as desired
                      Flex harUI Adobe Employee

                      The context object would hold i, j, tmpArray and startres local variables as

                      well as myObject1, value, bid1 and ask1.  Set j to -1, i to 0.

                       

                      On each call, if j == -1, you run the outer loop code, then set j to 0

                       

                      If j is not -1, run the inner loop code, and increment j.  At the end, if j

                      == tmpArray.length, then increment i and set j to -1 again.

                      • 8. Re: calllater not working as desired
                        ccdoss Level 1

                        I believe my understanding is at about 50% or so, but, just a couple more questions.

                        From your previous post, it looks like I should have myCalc look like this:

                         

                         

                        public static function myCalc(contextobj:object):ArrayCollection
                                {
                                    var i:int = contextobj.i;
                                    var j:int = contextobj.j;

                                    if(j==-1){

                                             contextobj.j = 0;
                                             contextobj.myObject1:Object = contextobj.tmpArray[i];
                                             //Set other values

                                  }

                                  else{
                                            for (j = 0; j < context.tmpArray.length; j++)
                                            {
                                             //inner loop stuff here 

                                            }

                                            contextobj.i++;

                                            contextobj.j = -1;
                                    }
                                   return ??;
                                }                   

                        So, I have two issues:

                         

                        1. From this, it looks like my inner loop would run all the way through, but your "If j is not -1, run the inner loop code, and increment j.  At the end, if j== tmpArray.length, then increment i and set j to -1 again." statement has me thinking the inner loop should be interrupted.
                        2. I'm not quite clear what I should return. I guess it would return i < tmpArray.length?
                        • 9. Re: calllater not working as desired
                          Flex harUI Adobe Employee

                          2.  You don't return anything.  The only caller of myCalc is the timer.  The

                          ArrayCollection you want to create should be created early and stored in the

                          context object, or created from an array stored in the context object when

                          the code finishes.

                           

                          1.  You should not have any "for" loops in the function.  You are

                          essentially flattening the loops.  Each call will either run the setup in

                          the outer loop, or run the code in the inner loop once and only once.

                          • 10. Re: calllater not working as desired
                            ccdoss Level 1

                            Okay, I believe I'm now at 75% understanding. I can flatten both loops so my code should be:

                            public static function myCalc(contextobj:object):ArrayCollection
                                    {
                                        var i:int = contextobj.i;
                                        var j:int = contextobj.j;

                                        if(j==-1){

                                                 contextobj.j = 0;
                                                 contextobj.myObject1:Object = contextobj.tmpArray[i];
                                                 //Set other values

                                      }

                                      else{
                                                if(j == contextob.tmpArray.length) //reached end of j loop

                                                {

                                                     contextobj.i++;

                                                     contextobj.j = -1;

                                                }

                                                else
                                                {
                                                 //inner loop stuff here

                                                 contextob.j++;

                                                }

                                               
                                        }
                                    }

                             

                            I guess that leaves me with he question of how does this thing terminate? In the example, the picture colorer would return false when it finished, thus causing the thread to cease.

                            • 11. Re: calllater not working as desired
                              Flex harUI Adobe Employee

                              It should return true or false (not an ArrayCollection) that indicates if

                              more loops are needed.

                              • 12. Re: calllater not working as desired
                                ccdoss Level 1

                                Works as desired. I had to make pseudothread.obj public so my handler could add the arraycollection to the datagrid, but this is wonderful. Now I just need to add a progress bar to report how much time is left.