How do i load 1000 Usercontrols in an Async fashion ?

已鎖定 How do i load 1000 Usercontrols in an Async fashion ?

  • vendredi 4 mai 2012 21:48
     
      A du code

    I'm loading thousands of lines from a database, and on each line im adding a usercontrol to the userinterface

    How do i program this to be Async ??

    pseudo code:

    var lines = db.executeCommand();
    
    while(lines.read())
    {
        Treeview.items.add(new TreeViewItem(lines.getValue());
    }

    i've tried wrapping it all into a Task, but then im told that i'm not allowed to touch the UIthread items :(

    it wouldn't matter to download all lines using an async command, since its the whole operation that takes CPU.. loading lines and adding items to UI is heavy in this case :-/


    • Modifié Montago vendredi 4 mai 2012 21:50
    •  

Toutes les réponses

  • vendredi 4 mai 2012 23:46
     
     
    It doesn't make sense to create thousands usercontrols, the user is never going to look at all of them. Can't you do this in a better way? Maybe add paging or limit the results to a reasonable number?
  • samedi 5 mai 2012 07:45
     
     
    It doesn't make sense to create thousands usercontrols, the user is never going to look at all of them. Can't you do this in a better way? Maybe add paging or limit the results to a reasonable number?
    The question was HOW to do it... not WHY ;-)
  • lundi 7 mai 2012 12:05
     
     

    Load all the database results into memory using async.

    Then do all the UI updates on the UI thread.

           -Steve


    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ
      and How to Implement IDisposable and Finalizers: 3 Easy Rules
    Microsoft Certified Professional Developer

    How to get to Heaven according to the Bible

  • lundi 7 mai 2012 13:49
     
     

    loading is one amtter, which is your instantiation like
    Button b1=new Button();

    but adding them is another issue, you can load the, in other thread, but not add them, because your form is in other thread, so in the end you need to have access to your other thread and keep it waiting for your access,

    so in your next thread, you can still decide again, after loading data, adding them will take too much time or less?

    and add them in one access or multiple access...

    forms provide MethodInvoker, which you will need to use to access the winApp thread, perform changes, and then exit...

  • lundi 7 mai 2012 13:53
     
     
    1 more thing you should know, which i didnt notice you need database loading, you can  also provide reacord reading with pagination...

    search "pagination" and query your data like that, now even sql doesn't become much busy
  • lundi 7 mai 2012 14:05
     
     

    Hi... 

    I tried loading all the elements from the database using Await + TaskEx, but the cost of this additional operation just meant longer loading time. The really heavy operation is creating all these UI elements and inserting them into the program. 

    So with this in mind, i think the smartest thing i could try is doing UI Virtualization along with Databinding, rather then data paging.

    I guess Aync is not really meant for heavy UI Loading :-(

  • mercredi 9 mai 2012 11:43
     
     Traitée

    I guess Aync is not really meant for heavy UI Loading :-(

    Precisely.

    UI updates have to be done on the UI thread [1]. There's nothing async - or anything else - can do to remove that fundamental restriction.

           -Steve

    [1] This is true today. Hopefully this will not always be the case. IIRC, WPF attempted to loosen this, but that attempt was unfortunately abandoned (probably to allow full Win32 interop) before WPF went live (perhaps that's where WPF gets its logical/visual tree separation?). From what I've heard, Metro has resurrected this concept - at least some animations may be done on non-UI threads, so other UI updates may be possible as well.


    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ
      and How to Implement IDisposable and Finalizers: 3 Easy Rules
    Microsoft Certified Professional Developer

    How to get to Heaven according to the Bible

  • lundi 25 juin 2012 12:05
     
     

    Don't Load your control in the form slowly :|

    do you ever hear of buffering or triple buffering ? in image processing?

    so we do same, you take a panel as your canvas, start load all buttons into it... (like drawing your shape into a bmp data structor)

    since you are in other thread, you need to invoke form to add this control into it...
    once it's done, just do add panel to your form (like putting that bmp into a picture box)

  • lundi 25 juin 2012 12:38
     
     

    Don't Load your control in the form slowly :|

    do you ever hear of buffering or triple buffering ? in image processing?

    so we do same, you take a panel as your canvas, start load all buttons into it... (like drawing your shape into a bmp data structor)

    since you are in other thread, you need to invoke form to add this control into it...
    once it's done, just do add panel to your form (like putting that bmp into a picture box)

    Loading 1000 controls in an invisible canvas will hog the CPU just as much as loading them into the destination. The program WILL/lag pause when you're loading them. 
  • samedi 30 juin 2012 12:40
     
     
    not in same thread ...

    even about paiting it take cpu time and process, but also control have their own painting, which if doesn't get called the application is faster,
    second we do this, to remove the refresh each time apply to the form...
  • samedi 30 juin 2012 19:20
     
     

    You can't load Usercontrols in other threads then UIThread... 

    do you have a sample of what you are talking about ?

  • dimanche 1 juillet 2012 07:44
     
      A du code

    Human can do any one he want to do, no one expect computer, then non expect assemblies and then all the kinda language and interfaces...

    the best practice is to do:

    1. Create a panel

    2. Load all button + calculating each position

    3. Set size of the panel / group box / or any thing you use as container

    4. Add the container to the windows form
        One thing happen in step 4 is a cross thread exception, so when you wanna add the controll:

        ☺ Check if invoke of form is required

        ☺ If is required (that all i saw was true) you invoke the windows form

        ☺ You add your container controls

    private Thread t;
            private void Form1_Load(object sender, EventArgs e)
            {
                t=new Thread(new ThreadStart(delegate
                                               {
                                                   int maxX = 0;
                                                   int maxY = 0;
                                                   Panel Panel1 = new Panel();
                                                   for (int i = 0; i < 100; i++)
                                                   {
                                                       for (int j = 0; j < 10; j++)
                                                       {
                                                           Button b = new Button();
                                                           b.Top = i*b.Height;
                                                           b.Left = j*b.Width;
                                                           Panel1.Controls.Add(b);
                                                           if (b.Top + b.Height > maxY) maxX = b.Top + b.Height;
                                                           if (b.Left + b.Width > maxX) maxX = b.Left + b.Width;
                                                       }
                                                   }
    
                                                   if(this.InvokeRequired)
                                                   {
                                                       this.Invoke(new MethodInvoker(
                                                                       delegate
                                                                           {
                                                                               this.Controls.Add(Panel1);
                                                                           }
                                                                       )
                                                           );
                                                   }
                                                   MessageBox.Show("Done");
                                               }));
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                if (t.ThreadState != ThreadState.Running && t.ThreadState!=ThreadState.Stopped)
                    t.Start();
            }