Click here to Skip to main content
16,022,060 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more: , +
I creating simple permutation code using c# app. Now I want to display a simple progressbar. Now if the program execute I want to check if the background is busy else I call the backgroundworker and show how many percent remaining.

What I have tried:

The code below I call when permutation code is execute.

static IEnumerable<IEnumerable<int>> GetPermutations(IEnumerable<int> indices, int limit)
        {
            if (limit == 1)
            {
                foreach (var index in indices)
                    yield return new[] { index };
                yield break;
            }

            var indicesList = indices.ToList();
            var subPermutations = GetPermutations(indices, limit - 1);

            foreach (var index in indicesList)
            {
                foreach (var subPerm in subPermutations)
                {
                    if (!subPerm.Contains(index))
                    {
                        yield return subPerm.Append(index);

                        //Cursor.Current = Cursors.WaitCursor;//for waiting..

                        //try
                        if (backgroundWorker1.IsBusy != true)
                        {
                            // Start the asynchronous operation.
                            backgroundWorker1.RunWorkerAsync();
                        }

                    }
                }
            }
        }

Error Image[^]

and this is the backgroundworker do work code.
private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
      {
          BackgroundWorker worker = sender as BackgroundWorker;

          for (int i = 1; i <= 10; i++)
          {
              if (worker.CancellationPending == true)
              {
                  e.Cancel = true;
                  break;
              }
              else
              {
                  // Perform a time consuming operation and report progress.
                  System.Threading.Thread.Sleep(500);
                  worker.ReportProgress(i * 10);
              }
          }
      }



My problem is, I dont know how to call backgroundWorker1 inside in static method. Please click the image above to see my error.
Posted
Updated 7-Sep-24 16:10pm
v2
Comments
George Swan 8-Sep-24 17:06pm    
That 'simple app' isn't very simple. It has recursive yield returns. Recursive algorithms can be difficult to figure out and the instances that have yield return statements are especially complex as you have to know the state of the variables inside the state machine that the yield return statement sets up. You have a lot of plates spinning there and you have done very well to keep them all up.

Just pass in the BackgroundWorker to the GetPermutations method as a parameter. Something along these lines.



C#
using System.ComponentModel;

namespace PersonComp
{
    internal class Program
    {
        static void Main()
        {

            TestPerms();

            Console.ReadLine();
        }
        public static void TestPerms()
        {
            BackgroundWorker? backgroundWorker = new()
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };
            backgroundWorker.DoWork += BackgroundWorkerDoWork;
            backgroundWorker.ProgressChanged += BackgroundWorkerProgressChanged;
            IEnumerable <int > index = [1, 2, 3];
            var perms = GetPermutations(index, 3, backgroundWorker);
            foreach (var perm in perms)
            {
                //wait for worker to finish
                Thread.Sleep(200);
                Console.WriteLine(string.Join(',', perm));

            }
            Console.ReadLine();

        }
        private static void BackgroundWorkerDoWork(object? sender, DoWorkEventArgs e)
        {

            BackgroundWorker? worker = sender as BackgroundWorker;

            for (int i = 1; i  <= 10; i++)
            {
                if (worker!.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    Thread.Sleep(10);
                    worker.ReportProgress(i * 10);
                }
            }
        }
        private static void BackgroundWorkerProgressChanged(object? sender, ProgressChangedEventArgs e)
        {
            Console.WriteLine(e.ProgressPercentage.ToString() + "%");
        }
        private static IEnumerable <IEnumerable <int > > GetPermutations(IEnumerable <int > fromArray,
                                                                     int chooseN,
                                                                     BackgroundWorker backgroundWorker)
        {
            if (chooseN == 1)//I can handle this on my own
            {

                foreach (var index in fromArray)//statemachine is running here
                {
                    yield return new[] { index };
                }
                //each int in fromarray has an array with [0]=the int
                yield break;
            }

            var indicesList = fromArray.ToList();
            //IEnumerable so call is deferred until enumerable is iterated
            //I can't handle this until I get the subPerms from a recursive call
            //with current chooseN param decreased by 1
            var subPermutations = GetPermutations(indicesList, chooseN - 1, backgroundWorker);
            //I have got the info required and can proceed
            foreach (var index in indicesList)
            {
                //statemachine is running here
                foreach (IEnumerable <int > subPerm in subPermutations)
                {
                    if (!subPerm.Contains(index))
                    {

                        //return the subperm as an item in IEnumerable <IEnumerable <int > >
                        yield return subPerm.Append(index);
                        if (backgroundWorker.IsBusy is false)
                        {
                            // Start the asynchronous operation.
                            backgroundWorker.RunWorkerAsync();
                        }
                    }

                }
            }
        }

    }
}
 
Share this answer
 
Comments
ras bry 13-Sep-24 19:03pm    
Thank you so much sir George Swan, its work
George Swan 14-Sep-24 1:26am    
You are very welcome. Your recursive method is excellent.
There are two types of "elements" that a class can have: static elements, and instance elements (where an element is a field, property, method, event, or delegate)

A static element is shared by all instances, and is accessed via the class name.
An instance element is unique to each different instance of the class and is accessed via the variable holding the instance reference.

Think about cars for a moment: all cars have a colour - but which colour it is depends on which specific car you are talking about. My car is black; your car is red; this car is green; that car is blue. Colour is an instance property of the Car class because you need to have a specific instance of a Car in order to ask the question "what colour is it?" - you can't say "what colour is a car?" because it's meaningless without saying which car you mean.
But cars have static properties as well: you can ask "how many wheels has a car?" because all cars have four wheels. (If it had two, it would be a motorbike, not a car)

Your backgroundWorker1 is non-static which means that it operates on a specific instance of a class rather than being generic to all instances. You can't access it directly from inside a static method because there is no class instance associated with it, so no such variable exists. The obvious solution (but don't do this) is to make the backgoundWorker1 static, but ... that will probably raise more problems later as there is then only one instance of the variable which is shared among all instances of the containing class. So if you have two MyClass instances (two forms, two UserControls, two Cars, whatever) then they will work on the same data.

I'd strongly suggest you sit down and think about what you are trying to do before you go any further, as I'm not sure you understand instances, static methods, and threading enough to proceed withoiut tying yourself in knots.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900