locked
Problem with WinJS.Promise RRS feed

  • Question

  • Hi,

    I am using a promise (WinJS.Promise) to read a stream in background. When I do animation in UI, if the promise is called, the animation will be affect. I don't know why? It's still works when Consummer Preview. How to solve that? 

    Thanks,

    Vivian

    Thursday, June 14, 2012 5:34 PM

All replies

  • Hi Vivian,

    Can you provide a code sample?  That would help us to reproduce the problem.

    David


    Dave Paquette @Dave_Paquette www.davepaquette.com

    Thursday, June 14, 2012 8:57 PM
  • Hi Dave,

    This is my simple example for this problem. When you click at button to add promise, animation will be affect. I realized that if I increase the max number for loop in promise, the animation will be affect too much.

    Html

    <body>
       <button id="btn">Add Promise</button>
       <canvas id="myCanvas" width="1368" height="768"></canvas> 
        
    </body>

    Javascript

    (function () {
        "use strict";
    
        var app = WinJS.Application;
        var activation = Windows.ApplicationModel.Activation;
        var btn;
        WinJS.strictProcessing();
    
        app.onactivated = function (args) {
            if (args.detail.kind === activation.ActivationKind.launch) {
                if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                    // TODO: This application has been newly launched. Initialize
                    // your application here.
                    btn = document.getElementById("btn");
                    btn.addEventListener("click", addPromise);
                    startAnimation();
                } else {
                    // TODO: This application has been reactivated from suspension.
                    // Restore application state here.
                    startAnimation();
                    btn = document.getElementById("btn");
                }
                args.setPromise(WinJS.UI.processAll());
            }
        };
    
        app.oncheckpoint = function (args) {
            // TODO: This application is about to be suspended. Save any state
            // that needs to persist across suspensions here. You might use the
            // WinJS.Application.sessionState object, which is automatically
            // saved and restored across suspension. If you need to complete an
            // asynchronous operation before your application is suspended, call
            // args.setPromise().
        };
    
        var offsetX = 0;
    
        function startAnimation() {
            var interval = setInterval(function () {
                offsetX += 30;
                if (offsetX > 1368)
                    offsetX = 0;
                drawRect();
            }, 30);
        }
    
        function drawRect() {
            var canvas = document.getElementById("myCanvas");
            var ctx = canvas.getContext("2d");
            ctx.clearRect(0, 0, 1368, 768);
            ctx.save();
            ctx.fillStyle = "yellow";
            ctx.fillRect(offsetX, 100, 300, 400);
            ctx.restore();
        }
    
        function addPromise() {
            console.log(" add promise ");
            asyncAdd(5, 6).then(function () {
                addPromise();
            });
        }
    
        function asyncAdd(num1, num2) {
            return new WinJS.Promise(function (complete) {
                setTimeout(function () {
                    for (var i = 0; i < 1000000; i++) {
                        var sum = num1 + num2;
                    } 
                    complete(sum);
                }, 100);
            });
        }
    
        app.start();
    })();

    Thanks,

    Vivian

    Friday, June 15, 2012 4:19 PM
  • So I have no idea what you're doing with addPromise and asyncAdd, they don't appear to do anything but burn through cycles.

    Anyway, your animation is probably stopping because you've hit a JS error and the whole JS file stops processing (including your interval based animation).

    for (var i = 0; i < 1000000; i++) {
        var sum = num1 + num2;
    } 
    complete(sum);

    You are defining sum within the for loop, but trying to reference it out of scope when you call complete.  Do this instead:

    var sum;
    
    for (var i = 0; i < 1000000; i++) {
        sum = num1 + num2;
    } 
    complete(sum);

    Check the output window for exception information, and it's also best to develop with first-chance-exceptions enabled: hit Ctrl+Alt+E to bring up the exception dialog, and then check "thrown" next to Javascript.

    • Edited by Bryan Thomas Friday, June 15, 2012 5:11 PM
    • Proposed as answer by Bryan Thomas Friday, June 15, 2012 5:11 PM
    • Unproposed as answer by Vivian Ng Tuesday, June 19, 2012 4:23 AM
    Friday, June 15, 2012 5:08 PM
  • Hi Bryan,

    I fix my code, but animation still slow. I have increase the max number for loop.

    function asyncAdd(num1, num2) {
            return new WinJS.Promise(function (complete) {
                setTimeout(function () {
                    var sum;
                    for (var i = 0; i < 10000000; i++) {
                        sum = num1 + num2;
                    } 
                    complete(sum);
                }, 100);
            });
        }

    Thanks,

    Vivian

    Monday, June 18, 2012 2:59 AM
  • Hi Bryan,

    Another question. As you said, when we've hit JS error, the whole JS stops processing. So if I use the method getFileAsync to check file and create new file when error, then every time the error hit, animation will be stop? I'm going crazy with RP, everything works fine with CP, but after upgrade to RP, animation always slow.

    Thanks,

    Vivian

    Monday, June 18, 2012 7:27 AM
  • Hi,

    Have anyone  found the answer yet? It's urgent to me now. Please help.

    Thanks,

    Vivian

    Wednesday, June 20, 2012 4:23 PM
  • Solve your problem ??

    Thursday, August 30, 2012 3:40 PM
  • Don't run your code in the debugger.  Deploy the project and run from the start screen to see what the real performance is like


    Jeff Sanders (MSFT)

    Thursday, August 30, 2012 6:16 PM
    Moderator
  • Hi Jeft,

    Although I run code from the start screen, the promise still affect performance of application if task in promise takes time too long.

    Vivian

    Friday, August 31, 2012 10:53 AM
  • Delete the asyncAdd function, you're burning up the UI thread with a bunch of unnecessary operations.

    Friday, August 31, 2012 4:29 PM
  • Correct Bryan,

    There is no Magic here Vivian!  If you are burning up CPU cycles there is no doubt your app will perform poorly!

    -Jeff


    Jeff Sanders (MSFT)

    Friday, August 31, 2012 5:18 PM
    Moderator
  • Hi Bryan and Jeff,

    I think you have missed Vivian's point. It doesn't matter that he is 'burning up cycles' - he is showing some sample code not his application. He is highlighting that he is doing some work IN A PROMISE that is affecting his UI thread. 

    I think what you need to respond with is HOW TO GET that work OFF THE UI thread so his UI thread, UI and animations are unaffected by 'low priority' background threads.

    Does this make sense? 

    I too am having the same problem 'burning up cycles' by doing jquery find and DOM work on screen scraped content (yuk!!). Although i put the code in promises (expecting it to execute on a background thread ) it doesn't seem to be happening, or if it is the threads are taking too much away from the UI thread. If they are executing on a background thread, then i need something akin to the c# - add the task to a queue to be executed when there is a spear thread (WPF style). 

    I'll post a solution when i find the equivalent in JS - if there is one. If you can't launch background threads in WinJS/Metro8 apps then there is almost no point writing them in Html/JS IMHO.

    Cheers

    Kle

    Thursday, September 6, 2012 1:41 AM
  • Have you considered using a worker for reading the stream (http://msdn.microsoft.com/en-us/library/windows/apps/hh453265.aspx)?

    Thursday, September 6, 2012 6:06 AM
  • Hi Kle,

    That's exactly what I want to know. Thank you very much!

    Vivian

    P/S: I am a female, not a male.

    Thursday, September 6, 2012 10:40 AM
  • Hi Law,

    I tried it, but it seems more slower than using Promise.

    Thanks,

    Vivian

    Thursday, September 6, 2012 10:41 AM
  • Correct, that is what background workers are for!

    PS, yes this will be a little slower because it will yield to the more important foreground thread.


    Jeff Sanders (MSFT)


    Thursday, September 6, 2012 11:50 AM
    Moderator
  • Have you had a chance to take a look at the HTML Independent animations sample (http://code.msdn.microsoft.com/windowsapps/Windows-8-Modern-Style-App-Samples). The sample is contained within the Win 8 Metro App sample pack. The sample also deals with a busy ui thread.
    Thursday, September 6, 2012 3:38 PM
  • Hi Bryan and Jeff,

    I think you have missed Vivian's point. It doesn't matter that he is 'burning up cycles' - he is showing some sample code not his application. He is highlighting that he is doing some work IN A PROMISE that is affecting his UI thread. 

    I think what you need to respond with is HOW TO GET that work OFF THE UI thread so his UI thread, UI and animations are unaffected by 'low priority' background threads.

    Does this make sense? 

    I too am having the same problem 'burning up cycles' by doing jquery find and DOM work on screen scraped content (yuk!!). Although i put the code in promises (expecting it to execute on a background thread ) it doesn't seem to be happening, or if it is the threads are taking too much away from the UI thread. If they are executing on a background thread, then i need something akin to the c# - add the task to a queue to be executed when there is a spear thread (WPF style). 

    I'll post a solution when i find the equivalent in JS - if there is one. If you can't launch background threads in WinJS/Metro8 apps then there is almost no point writing them in Html/JS IMHO.

    Cheers

    Kle

    Promises are async, but JavaScript doesn't have concurrency. In other words: something run setImmediate doesn't run on a different thread at the same time, it's the same thread that time slices-operations so they appear to be concurrent.

    So yes, use a worker if you want to do concurrent processing while keeping the UI thread snappy. Or you can implement a Native or C# library to do your processing, there you might have better tools and better performance (and explicit control over threads).

    Thursday, September 6, 2012 5:08 PM
  • Hi All,

    Firstly, Vivian, sorry. bad assumption. If your still having trouble with web workers check these out.

    Win RT, Promises and Web workers - nice 3 page article on combining the whole lot. 

    http://www.i-programmer.info/ebooks/creating-javascripthtml5-metro-applications/4713-winrt-javascript-web-workers-a-promises.html

    another good article

    http://software.intel.com/en-us/articles/using-web-workers-to-improve-the-performance-of-metro-html5-javascript-apps/?cid=sw:prccsdn229043

    Secondly, thanks for the replies. 

    I spent the entire day yesterday doing pretty much what you suggested - using web workers. I found out the whole javascript/async thing with some further reading. 

    My problem now, as i assume some other people who are running workers is parsing the HTML that is returned. 

    Because the worker doesn't have access to the DOM, document or window i am finding it hard to work with the html returned from a WinJS xhr request. Specifically i need to screen scrape some extra information that is not in an RSS feed. 

    - JQuery doesn't work as it needs the DOM/document

    - htmlparser.js (found it on google) - a pure javascript html parser doesn't work. still required the document... 

    - xml for script (again, found on google) doesn't work even though it supports parsing W3C XML/DOM using pure javascript. this time the page returned is not VALID!!! the first page i tried, by chance, has a </br /> tag!!! and the parser fails... 

    Short of re-writing the JS for XML for Script i have run out of ideas for parsing and querying the returned document, effectively making my web worker useless as i need to get the searching/innerHTML calls off the UI thread as they are the culprits. 

    any suggestions welcome, 

    Thursday, September 6, 2012 11:34 PM
  • Hi,

    thanks for that Bryan, that was one of my work mates said. 

    I will give it a go today,

    shouldn't take long, 

    cheers

    kle

    Monday, September 10, 2012 12:26 AM