none
c# uwp : How to force a screen fresh on a canvas RRS feed

  • Question

  • I am moving an object that is a child on a canvas. So, my processing goes off and may do hundreds of moves as each moving item may initiate others to move. I have two problems. 

    1: The screen refreshes only when complete.  You do not get to see what happened in between.  In my old code, I would refresh the screen every 10 moves or so.  The value was a user set option. 

    2: Debugging.  It would make debugging much easier if it refreshed every move.  I could comment that code to stop that when not debugging.  Right now, I am having a debug/conversion issue and am doing recursion.  It is difficult to track if you cant see what happened on screen.

    VB had a DoEvents.  I did find posts about <ctrl>.Update  invalidate and refresh, but they dont seem to be available. 

    Am I missing something.  There is a canvas.UpdateLayout, but I dont think that is it. 

    Sunday, October 27, 2019 7:23 PM

Answers

  • Hello,

    Your code looks nearly perfect. By just altering setImagePosition(...) to an awaitable-return-type-function, it would work.

            // Change return-type from "void" to "Task" to make it awaitable. 
    	// 
            async Task setImagePosition(int intRow, int intCol, int intCount)
            {
                MyImage.SetValue(Canvas.TopProperty, (intRow * MyImage.Height) + 1);
                MyImage.SetValue(Canvas.LeftProperty, (intRow * MyImage.Width) + 1);
                Message.Text = "Max: " + intCount.ToString() + "   :::  " +
                               "Row: " + intRow.ToString() + "   :::  " +
                               "Col: " + intCol.ToString();
    
                int it = intCount % 5;
                if (it == 0)
                   // canPlayBoard.UpdateLayout();
                // await Task.Delay(5000);
                    await Task.Delay(TimeSpan.FromSeconds(5));
            }
    
    	// BTW, when the asynchronous function need to return some value, use Task<T> as follows. 
    	// 
            async Task<int> myDelay()
            {
                await Task.Delay(TimeSpan.FromSeconds(1.5));
                return 42;
            }

    Then,

            async void myInit()
            {
                Message.Text = "Count: ";
                Random rng = new Random();
    
                int intMax = 0;
                int randomY = 0;
                int randomX = 0;
    
                intMax = rng.Next(5000, 10000);
                for (int intRand = 1; intRand < intMax; intRand++)
                {
                    randomY = rng.Next(1, 10);
                    randomX = rng.Next(1, 15);
    
                   await setImagePosition(randomY, randomX, intRand); 
                }
                // int intTest = await myDelay();
            }

    For details of Task-based asynchronous pattern, see documentation.

    • Marked as answer by ScCrow2 Thursday, November 7, 2019 1:55 PM
    Thursday, November 7, 2019 3:07 AM

All replies

  • Hi.

    If I understand correctly, the move process will last a long time and only parts of the elements will move at the same time, right? Then you want to refresh the layout every 10 elements moves, right? Are you using animation to move your elements or you are using other ways to move the elements?

    Generally, we will update the layout using UpdateLayout function. May I know why you say that isn't it? It gives errors or it has some other unexpected behavior?

    Best regards,

    Roy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, October 28, 2019 3:20 AM
    Moderator
  • THx for reply.

    Sorry.. lot of words.  If UpdateLayout is the thing to use, I'm on it and thanks.  Often, I have trouble with navigating to the proper documentation.

    The program is a game.  The character moves 1 square on a grid and by doing so, may cause a 1 or more rocks to fall, arrows to take off etc. The non char moving is recursive, an arrow may shoot completely across the screen, and along the way cause rocks to fall, which may cause many other things to start moving.  Moving of these items is to move positions in a grid.  Currently, the "moving" routine starts and nothing gets updated visually until everything is finished.  The player has no idea what occurred visually as to what happened.  They just see the end results.  So, if there is a refresh every 5 moves, the arrow may move 5 spots and you see that it moved.  Then another 5.  Or,, it moves 3, a rock moves 2, etc.  The game board is 17x40, so there can be a lot of objects on the screen.

    If I were to set the refresh on every move temporarily, I could see every move while tracing through the code, but would slow down the game but would be useful in debugging.

    As I recall it, VB or C way back had a refresh.  Then, I had to use DoEvents. This program has been updated and converted from c to some pre vb6, to others.   I am trying to update it to c#. I am also close to giving up  up and going back to VB.  It would be a much quicker program update.

    It is a clone of a game and there are 85 screen levels with solutions.  If things do not stay processed in the same order as it has always been, it will probably screw up many of them if not most.  Once, several years ago, I was having a similar problem.  About the only suggestion I got was re-write it using objects that handle their own moving.  You can see, that is not an option.  That may be a fine idea if its a new game with no existing screens.

    I am not using Animation.  Moving is just repositioning an image to a new place in the grid, removing it from the canvas, etc.

    I tried the canvas.UpdateLayout.  Nothing happened. That code was quickly deleted, so it can easily easily be I just made mistake.   My research found examples using  update, invalidate, refresh, etc. so I was starting the test thinking it would not work.  Those methods dont seem to be part of  UWP.  If that is the thing to use Great.  I will apologize and try again. 

    Monday, October 28, 2019 10:05 PM
  • I tired again

                        }
                    }
                    canvasGameBoard.UpdateLayout();
                }
                catch (Exception ex)
                {

    There were no u0pdates until processing finished.  There was no error thrown.

    Monday, October 28, 2019 11:35 PM
  • Hi,

    I understand what you are trying to do now. So you are not using animation here. How do you move your elements and how do you move the other ones when the first is moved? Could you please share a simple repro demo about this with me so I could try to take a look at this? A simple gird with some elements, if one element moves, then some elements will move after that like your app. Could you build it in a normal blank UWP app and share it with me?

    Best regards,

    Roy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, October 29, 2019 1:57 AM
    Moderator
  • Hi Roy.

    Its a good day. I found a mistake and several things are working now.  Still a lot to do.  In this conversion, I'm changing how some of the underlaying stuff works stuff and may add 2 new features.  This has been my learn a new language program for many years.  It kind of pissed me off.  I put up a free version in the windows store. NO one other than friends and family ever downloaded it, despite it having nothing but 5 star reviews.

    OK. I lied below.  How do I send you something?   And what do you want me to send?

    Ill try to answer a couple of questions.  The 1st movement is actually pretty easy.  Each image is placed into a canvas with canvas.add. and using a canvas left/right tp position it.  So  ele1.canvas.left = 5 * Ele_width    ele1.canvas.right= 10* Ele_height   would put it in 5th col, row 10. So changing its position is just upping one of those two. No diagonal moves, but you could do that.  In my situation, I simply remove the old element, and create a new one in the new position.  There are other things going on, and this probably  just as efficient.

    The next part is the items that move themselves and continue to move until they cant. That is the massive mess that is in the program.  Its what you get from all the old and converted code.  I think it originally was Atari code.

    When My char moves, he checks where he is moving to, then from the original position, left, right & behind , then left and right of behind. Each of those positions have to be checked to see if anything can move. If they can move (say its an arrow),  then that same process has to occur for each moving item.  All this moving processing was originally done recursively, but back on a x86, probably 8mhz cpu, i ran out of memory.  I had to fake the recursion.  Data is pushed on to a stack, and popped off when its their time again. You can see that say 30 things get to moving, there could easily be a thousand things on the stack.  Debugging is not so easy sometimes.  Also the sub is not short. That one sub is about 1300 lines. And it works using several others.

    I said all that .. a quick short pgm, probably not. I can pack up the code as is, and send it to you. I don't know if your allowed todo that or not. I also have the old VB code which works and I could pack it up. But it worked really differently, ergo the changes I'm making now. This new version will be way better. If I can get that screen paint thing to work.

    I am going to send you a wav.  Its the solution of the entry level screen. At one time, I had a web page and made the video to show a sample screen. Sorry for the sound. I didn't realize it was in the wav.


    Tuesday, October 29, 2019 9:33 PM
  • Hello ScCrow2,

    As a counterpart of VB's DoEvents in C#, try using ...

    await Task.Delay(10); // 10ms

    anyway.

    Wednesday, October 30, 2019 12:34 AM
  • I will give this a try.  I am currently in the middle of converting one of the methods to doing it a new way.  It will take a little time before I can test that.

    And Roy, when I get time, I will try to create a short version of something to demo the issue.  I have to get a few of these things converted first.

    Wednesday, October 30, 2019 9:31 PM
  • Hi,

    Never mind. You could ask about this anytime in the forum. Good luck with your work!

    Best regards,

    Roy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, October 31, 2019 6:56 AM
    Moderator
  • Hi again.

    I made a short demo program.  I also tried the await "Task.  Not sure I did either of them correctly, but neither worked for me.

    How to make it available?  I dont see any upload options.  Its relatively short.  I guess I can slam all the code into a reply.

    Let me know, and thanks.

    I suppose I can try to do a storyboard on each item, but that sure seems like a waste of processing time.

    Tuesday, November 5, 2019 1:33 PM
  • Hi,

    You could upload the sample to the github and share the link with me. Please delete all the sensitive code and just keep the code that could reproduce the behavior.

    Best regards,

    Roy


    "Developing Universal Windows apps" forum will be migrating to a new home on Microsoft Q&A (Preview)!
    We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A (Preview)!
    For more information, please refer to the sticky post.

    Wednesday, November 6, 2019 9:26 AM
    Moderator
  • Thanks Roy

    I am not familiar with GetHub.  I just created an account and put the project up.  I Think one of these two is the link.

    /CanvasUpdateLayout

    https://github.com/dkcrotty/CanvasUpdateLayout.git

    The Code is Nothing sensitive.  Its just a short quick and dirty thing.  It just shows that no screen updates are occurring .

    ***** Just got a bunch of stuff working.  :)

    OK.  Now, I really need to get a way to refresh the screen while processing.  

    In the game, you press arrow keys to make a move.  That is fine and it all works.

    I have a solve Button.  The users keystrokes have all been saved.  ON a "Solve" click, those keystrokes are "Played" one at a time from a string of saved keystrokes.  The process runs and completes.  The problem is that you do NOT see any movement.  You only get the Congratulations at the end and all the final screen updates.

    I have not tried it, but I dont think an animation will solve this problem either. I do see some animations occur at the end, but no movement. 

    I did include    canvasGameBoard.UpdateLayout();    But it doesn't seem to work.  Good chance that I am just applying it incorrectly. 

    Wednesday, November 6, 2019 3:22 PM
  • Hello,

    Your code looks nearly perfect. By just altering setImagePosition(...) to an awaitable-return-type-function, it would work.

            // Change return-type from "void" to "Task" to make it awaitable. 
    	// 
            async Task setImagePosition(int intRow, int intCol, int intCount)
            {
                MyImage.SetValue(Canvas.TopProperty, (intRow * MyImage.Height) + 1);
                MyImage.SetValue(Canvas.LeftProperty, (intRow * MyImage.Width) + 1);
                Message.Text = "Max: " + intCount.ToString() + "   :::  " +
                               "Row: " + intRow.ToString() + "   :::  " +
                               "Col: " + intCol.ToString();
    
                int it = intCount % 5;
                if (it == 0)
                   // canPlayBoard.UpdateLayout();
                // await Task.Delay(5000);
                    await Task.Delay(TimeSpan.FromSeconds(5));
            }
    
    	// BTW, when the asynchronous function need to return some value, use Task<T> as follows. 
    	// 
            async Task<int> myDelay()
            {
                await Task.Delay(TimeSpan.FromSeconds(1.5));
                return 42;
            }

    Then,

            async void myInit()
            {
                Message.Text = "Count: ";
                Random rng = new Random();
    
                int intMax = 0;
                int randomY = 0;
                int randomX = 0;
    
                intMax = rng.Next(5000, 10000);
                for (int intRand = 1; intRand < intMax; intRand++)
                {
                    randomY = rng.Next(1, 10);
                    randomX = rng.Next(1, 15);
    
                   await setImagePosition(randomY, randomX, intRand); 
                }
                // int intTest = await myDelay();
            }

    For details of Task-based asynchronous pattern, see documentation.

    • Marked as answer by ScCrow2 Thursday, November 7, 2019 1:55 PM
    Thursday, November 7, 2019 3:07 AM
  • Thanks Roy.  Works as advertised with your suggested updates. :-)   Now I need to apply it to the Real program.

    and a note for anyone else reading this

    I did not need the      canvas.UpdateLayout

    I did need                 await Task.Delay(TimeSpan.FromSeconds(.001));

    without the delay, it just ran too fast to see any movement on the screen.

    Thursday, November 7, 2019 2:33 PM
  • Roy, can I ask one more question/opinion? 

    My sample app worked just fine. So I applied the same to the game.  So far, it just isnt working.  By that I mean , it may be working, but the results are not even close to being usable.

    Here is what I think, and I may be wrong.  The "Move" proc is called from a few other procs.  In Not Asysc world, this all works, we just dont get to see the move until the end. So I made all the changes everywhere.  Since that proc did not have an await, its working fine. I also have the canvas.UpdateLayout in there, no errors. I press my "Solve" button and it runs to the end, no updates till done, but it completes. Then I see the storyboard of the explosion that killed the player..

    If I make the changes, NO storyboard explosions are seen. I'm not even sure it completed. It probably did, but I cant tell visually (that's my fault, I should check it).  Some of the objects move, mostly in bursts. So it does seem to be processing.

    I think that it is the Async that is messing up things. As I understand it, We kick off the move to a new thread and continue on.  But I am kicking off many moves. I think they are not returning in the order they were submitted.  In non async, when a move was made, processing continued in order and all was well.  So in my little world, I actually need it to go synchronously. Things need to happen in the proper order.  I don't want the user to be able to click on some other button to click kick off some action until everything is finished. 

    A re-paint (doEvents or app.refresh) worked fine.

    Please dont tell me that I have to go back to VB.  I like the layout, Xaml and C# way too much for the front end instead of forms. Currently, the playback and the single moves are both ...  just not OK.  The original game worked that way. You just got to see the results.  Seeing where the objects move was a huge improvement.  I dont want to think about what problems this will cause in the Screen Designer.

    Assuming that I just cant do that.  Do you have a suggestion?  Xarmin.  WPA? VB. Not c++.  Too old to make that move.  My old VB version works.  I may have to trash all this C# coding and update the VB version. 

    Maybe MS should just expose a screen.refrsh.  :-)  THe call is there somewhere since VB can do it.

    Friday, November 8, 2019 12:00 AM
  • Im trying it again.  Its almost always something stupid that I did.
    Friday, November 8, 2019 2:38 PM
  • Ok. All the needed procs are await/asyched with no issue. I have put the following code into 3 places, none of them are in the move routine, they are in the calling subs.

          canvasGameBoard.UpdateLayout();
          await Task.Delay(TimeSpan.FromSeconds(.00));

    The first line seems to make no difference. I commented it and uncommented it and tested it both ways.

    Then I set the TaskDelay levels to .01, highest first and tested. NO other changes.  AT the highest level, no problem, but that level us mostly only the player move is affected. The recursive falling stuff not occurring there.  At the lower level, I get sporadic movement, the player has not moved and I dont see the StoryBoard animations. The results are not valid.

    ON the good side, the changes to Async/awaitare all in and functioning. 

    Friday, November 8, 2019 6:07 PM