Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Putting event handler codes inside DoWork delegate for asynchronous multi-threaded calculations

Putting event handler codes inside DoWork delegate for asynchronous multi-threaded calculations

Scheduled Pinned Locked Moved C#
questionwpfdesign
11 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Code4Ever

    I have the following code for getting data and paginating them inside the DataGrid:

        private void dataPager\_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
        {
            List data;
            using (var \_sqliteContext = new SQLiteContext())
            {
                data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList();
            }
            dataPager.LoadDynamicItems(args.StartIndex, data);
            //resetting cache for all pages.
            (dataPager.PagedSource as PagedCollectionView).ResetCache();
        }
    

    Now, I want to use background worker to do calculation in an another thread. I make the following changes:

    private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
    {
    BackgroundWorker worker = new BackgroundWorker();
    worker.WorkerReportsProgress = false;

            worker.DoWork += worker\_DoWork;
            worker.RunWorkerAsync();
    
        }
    

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
    List data;
    using (var _sqliteContext = new SQLiteContext())
    {
    data = _sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList();
    }
    dataPager.LoadDynamicItems(args.StartIndex, data);
    //resetting cache for all pages.
    (dataPager.PagedSource as PagedCollectionView).ResetCache();
    }

    But, worker_DoWork does not have any overload. I cannot pass args to worker_DoWork How can I solve it?

    OriginalGriffO Offline
    OriginalGriffO Offline
    OriginalGriff
    wrote on last edited by
    #2

    The DoWorkEventArgs class includes an Argument Property[^] You can set that to an instance of any class (or struct) to pass whatever you need in. It also contains a Result[^] property for passing completed data back to the caller via the RunWorkerCompleted Event[^]

    "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!

    "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
    "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt

    C 2 Replies Last reply
    0
    • OriginalGriffO OriginalGriff

      The DoWorkEventArgs class includes an Argument Property[^] You can set that to an instance of any class (or struct) to pass whatever you need in. It also contains a Result[^] property for passing completed data back to the caller via the RunWorkerCompleted Event[^]

      "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!

      C Offline
      C Offline
      Code4Ever
      wrote on last edited by
      #3

      Is it possible to pass more than one instance of any class? Do I need to use List in this case?

      OriginalGriffO 1 Reply Last reply
      0
      • OriginalGriffO OriginalGriff

        The DoWorkEventArgs class includes an Argument Property[^] You can set that to an instance of any class (or struct) to pass whatever you need in. It also contains a Result[^] property for passing completed data back to the caller via the RunWorkerCompleted Event[^]

        "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!

        C Offline
        C Offline
        Code4Ever
        wrote on last edited by
        #4

        I used the following code for getting data from SQLite:

        private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
        {
        List list = new List()
        {
        int.Parse(args.StartIndex.ToString()),
        int.Parse(args.PageSize.ToString())
        };

                BackgroundWorker worker = new BackgroundWorker();
                worker.WorkerReportsProgress = false;
        
                worker.DoWork += worker\_DoWork;
                worker.RunWorkerAsync(list);
            }
        
            void worker\_DoWork(object sender, DoWorkEventArgs e)
            {
                List value = (List)e.Argument;
                List data;
                using (var \_sqliteContext = new SQLiteContext())
                {
                    data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(value\[0\]).Take(value\[1\]).ToList();
                }
                this.Dispatcher.Invoke(() =>
                {
                    dataPager.LoadDynamicItems(value\[0\], data);
                    //resetting cache for all pages.
                    (dataPager.PagedSource as PagedCollectionView).ResetCache();
                });
            }
        

        There is no runtime error but the table in the UI is empty.

        OriginalGriffO Richard Andrew x64R 2 Replies Last reply
        0
        • C Code4Ever

          Is it possible to pass more than one instance of any class? Do I need to use List in this case?

          OriginalGriffO Offline
          OriginalGriffO Offline
          OriginalGriff
          wrote on last edited by
          #5

          You can use any object - so an int, a MyClass, a collection of IEnumerable objects, an array ... literally anything you need to. Just be aware that you are multithreaded so you need to ensure thread safety if the argument data is going to be even looked at by two different threads, and that Control derived classes can only be accessed from the thread that created them (the UI thread). But you almost certainly knew that ... I added it for those other readers who are just getting started with threading.

          "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!

          "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
          "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt

          1 Reply Last reply
          0
          • C Code4Ever

            I used the following code for getting data from SQLite:

            private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
            {
            List list = new List()
            {
            int.Parse(args.StartIndex.ToString()),
            int.Parse(args.PageSize.ToString())
            };

                    BackgroundWorker worker = new BackgroundWorker();
                    worker.WorkerReportsProgress = false;
            
                    worker.DoWork += worker\_DoWork;
                    worker.RunWorkerAsync(list);
                }
            
                void worker\_DoWork(object sender, DoWorkEventArgs e)
                {
                    List value = (List)e.Argument;
                    List data;
                    using (var \_sqliteContext = new SQLiteContext())
                    {
                        data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(value\[0\]).Take(value\[1\]).ToList();
                    }
                    this.Dispatcher.Invoke(() =>
                    {
                        dataPager.LoadDynamicItems(value\[0\], data);
                        //resetting cache for all pages.
                        (dataPager.PagedSource as PagedCollectionView).ResetCache();
                    });
                }
            

            There is no runtime error but the table in the UI is empty.

            OriginalGriffO Offline
            OriginalGriffO Offline
            OriginalGriff
            wrote on last edited by
            #6

            Start with the debugger and see what data contains before you start the Invoke.

            "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!

            "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
            "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt

            C 1 Reply Last reply
            0
            • OriginalGriffO OriginalGriff

              Start with the debugger and see what data contains before you start the Invoke.

              "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!

              C Offline
              C Offline
              Code4Ever
              wrote on last edited by
              #7

              I debugged. Before Dispatcher.Invoke, the data is full of 50 records. But something happens in Dispatcher.Invoke and prevent data to be shown in the UI.

              1 Reply Last reply
              0
              • C Code4Ever

                I have the following code for getting data and paginating them inside the DataGrid:

                    private void dataPager\_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
                    {
                        List data;
                        using (var \_sqliteContext = new SQLiteContext())
                        {
                            data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList();
                        }
                        dataPager.LoadDynamicItems(args.StartIndex, data);
                        //resetting cache for all pages.
                        (dataPager.PagedSource as PagedCollectionView).ResetCache();
                    }
                

                Now, I want to use background worker to do calculation in an another thread. I make the following changes:

                private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
                {
                BackgroundWorker worker = new BackgroundWorker();
                worker.WorkerReportsProgress = false;

                        worker.DoWork += worker\_DoWork;
                        worker.RunWorkerAsync();
                
                    }
                

                void worker_DoWork(object sender, DoWorkEventArgs e)
                {
                List data;
                using (var _sqliteContext = new SQLiteContext())
                {
                data = _sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList();
                }
                dataPager.LoadDynamicItems(args.StartIndex, data);
                //resetting cache for all pages.
                (dataPager.PagedSource as PagedCollectionView).ResetCache();
                }

                But, worker_DoWork does not have any overload. I cannot pass args to worker_DoWork How can I solve it?

                L Offline
                L Offline
                Lost User
                wrote on last edited by
                #8

                Your BackgroundWorker is going to go out of scope; I haven't used that pattern so if it gets "busy", it will be hard to tell, if at all.

                "Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I

                1 Reply Last reply
                0
                • C Code4Ever

                  I used the following code for getting data from SQLite:

                  private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
                  {
                  List list = new List()
                  {
                  int.Parse(args.StartIndex.ToString()),
                  int.Parse(args.PageSize.ToString())
                  };

                          BackgroundWorker worker = new BackgroundWorker();
                          worker.WorkerReportsProgress = false;
                  
                          worker.DoWork += worker\_DoWork;
                          worker.RunWorkerAsync(list);
                      }
                  
                      void worker\_DoWork(object sender, DoWorkEventArgs e)
                      {
                          List value = (List)e.Argument;
                          List data;
                          using (var \_sqliteContext = new SQLiteContext())
                          {
                              data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(value\[0\]).Take(value\[1\]).ToList();
                          }
                          this.Dispatcher.Invoke(() =>
                          {
                              dataPager.LoadDynamicItems(value\[0\], data);
                              //resetting cache for all pages.
                              (dataPager.PagedSource as PagedCollectionView).ResetCache();
                          });
                      }
                  

                  There is no runtime error but the table in the UI is empty.

                  Richard Andrew x64R Offline
                  Richard Andrew x64R Offline
                  Richard Andrew x64
                  wrote on last edited by
                  #9

                  Could it be that in worker_DoWork your variable data is going out of scope when the function ends?

                  The difficult we do right away... ...the impossible takes slightly longer.

                  1 Reply Last reply
                  0
                  • C Code4Ever

                    I have the following code for getting data and paginating them inside the DataGrid:

                        private void dataPager\_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
                        {
                            List data;
                            using (var \_sqliteContext = new SQLiteContext())
                            {
                                data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList();
                            }
                            dataPager.LoadDynamicItems(args.StartIndex, data);
                            //resetting cache for all pages.
                            (dataPager.PagedSource as PagedCollectionView).ResetCache();
                        }
                    

                    Now, I want to use background worker to do calculation in an another thread. I make the following changes:

                    private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
                    {
                    BackgroundWorker worker = new BackgroundWorker();
                    worker.WorkerReportsProgress = false;

                            worker.DoWork += worker\_DoWork;
                            worker.RunWorkerAsync();
                    
                        }
                    

                    void worker_DoWork(object sender, DoWorkEventArgs e)
                    {
                    List data;
                    using (var _sqliteContext = new SQLiteContext())
                    {
                    data = _sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList();
                    }
                    dataPager.LoadDynamicItems(args.StartIndex, data);
                    //resetting cache for all pages.
                    (dataPager.PagedSource as PagedCollectionView).ResetCache();
                    }

                    But, worker_DoWork does not have any overload. I cannot pass args to worker_DoWork How can I solve it?

                    Richard DeemingR Offline
                    Richard DeemingR Offline
                    Richard Deeming
                    wrote on last edited by
                    #10

                    Assuming you have to call the LoadDynamicItems from within the event handler, moving the data-loading code to a background thread really won't accomplish anything. You'll still need to block in the event handler until the background thread has finished, so you'll be using two threads to do what you're currently doing with one. You'll also potentially run into issues if you're working in a framework with a concept of a "UI thread"; the control will most likely expect the LoadDynamicItems method to be called from the UI thread, not a background thread, so you'll end up getting an exception.


                    "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                    "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                    C 1 Reply Last reply
                    0
                    • Richard DeemingR Richard Deeming

                      Assuming you have to call the LoadDynamicItems from within the event handler, moving the data-loading code to a background thread really won't accomplish anything. You'll still need to block in the event handler until the background thread has finished, so you'll be using two threads to do what you're currently doing with one. You'll also potentially run into issues if you're working in a framework with a concept of a "UI thread"; the control will most likely expect the LoadDynamicItems method to be called from the UI thread, not a background thread, so you'll end up getting an exception.


                      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                      C Offline
                      C Offline
                      Code4Ever
                      wrote on last edited by
                      #11

                      Can you please explain it using some codes?

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups