Click here to Skip to main content
15,886,840 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Ex:-
C#
for(int i=0;i <=10;i++)
{
Messagebox.show(i.ToString());

//*Here I want something like pause, so if I click Pause button of WinForms and consider i=4, then this loop must pause, until not going to click on Resume button.
And if now click on Resume button after 5-10 minutes then it should start from same state where we paused (from i=4) *//

//Why I am looking for this
I extract list of .sql files in a folder then open each .sql file and do some text extraction to extract table name, and then I create script with help of these tables names in a loop, file by file 

so I want a pause button in between of loop to see Original text, extract table name and further dynamically created text on Winforms, if required to check randomly. For which I am looking Pause/Resume functionality in a loop(I am using foreach loop)*//
}

//Actual Program

try
{
                
//using LINQ
StringBuilder result = new StringBuilder();
string connetionString = null;
foreach (XElement level1Element in XElement.Load(ManifestFile).Elements("Objects"))
{
if (level1Element.Attribute("AssetClass").Value.ToUpper() == "Common".ToUpper())
{ 
connetionString = System.Configuration.ConfigurationManager.AppSettings["UAT_EQ"].ToString();
}
cnn = new SqlConnection(connetionString);
cnn.Open();
CreateTempTable(cnn);
                    
result.AppendLine(level1Element.Attribute("AssetClass").Value);
foreach (XElement level2Element in level1Element.Elements("DeployObject"))
{
result.AppendLine("  " + level2Element.Value);
TxtReader(level1Element.Attribute("AssetClass").Value.ToString(),level2Element.Value.ToString(), string.Concat(string.Concat(fPath, level1Element.Attribute("AssetClass").Value), string.Concat("\\", level2Element.Value)), cnn);
Thread.Sleep(1000); //Here I am looking for Pause and Resume functionality
}
ExtractTableName(cnn);
CreateFile(cnn);
cnn.Close();
} 


Please help on this.

What I have tried:

Tried google and found:-
Pause and Resume a For-Loop in C# - Stack Overflow[^]
BackgroundWorker Class (System.ComponentModel)[^]

But problem is backgroundWorker1.CancelAsync(); don't pause loop, it stops loop , but I want loop to start from that position where we paused it, on click of Resume.
Posted
Updated 28-Nov-16 9:53am
v5
Comments
Philippe Mori 28-Nov-16 9:52am    
How long do it take to process one item? When pausing, can the current item be terminated? How many item do you have?

These details are important to suggest best solution as otherwise we only can make a guess but it might no be the best solution.

By the way, you probably don't want to keep the connection open while in pause state.
StackQ 29-Nov-16 4:49am    
//Why I am looking for this
I extract list of .sql files from xml file, then open each .sql file and do some text extraction to extract table name, and then I create required script with help of these extracted tables names in a loop, one by one

Required answers of above comment:-
-To process one item it will hardly take 1-2 seconds.
-When pausing, don't want to terminate anything, just want to pause it.(Suppose I have 10 .sql file, in loop if i=5, means I processed 5 files, now if paused then it will get pause,and if resume from here after 10-15 minutes then processing should get start from i=6, means from 6th file)
-How many item do you have?> I have xml file where there will be list of .sql file, max number of .sql file count will be 400 to 500

And yes I don't want to keep the connection open, while in pause state. But it will be not an issue, coz it's UAT environment,and everything handled only with Global Temp table and temp stored procedures only. There is no actual object involved from database.

I came up with this idea:

C#
class Program
    {
        static volatile bool paused = false;
        static volatile bool finished = false;
        void PauseLoop()
        {
            for(int i=0; i<1e6;i++)
            {
                while (paused) { }
                Console.WriteLine(i);
            }
            finished = true;
        }

        static void Main(string[] args)
        {
            Program p = new Program();
            ThreadStart ts = new ThreadStart(p.PauseLoop);
            Thread t = new Thread(ts);
            t.Start();

            char c;
            while(!finished)
            {
                if (Console.ReadKey().Key == ConsoleKey.P)
                    paused = true;
                else
                    paused = false;

                Console.WriteLine(paused ? "Pause" : "Resume");
            }

            Console.ReadKey(); // pause while testing

        }
 
Share this answer
 
Timers are a good alternative, to make sure you do not waste ressources when you're supposed to be pausing, like optionally if you instead were to loop something until called to action

C#
using System;
using System.Threading;

namespace sandbox
{
    class PausableBase : IDisposable
    {
        private Timer _t;
        private bool _tickExecuting;

        public event EventHandler Tick;

        public PausableBase()
        {
            _t = new Timer(TimerTick, null, Timeout.Infinite, Timeout.Infinite);
        }

        private void OnTick(object sender, EventArgs e)
        {
            Tick?.Invoke(sender, e);
        }
        public void Pause()
        {
            _t.Change(Timeout.Infinite, Timeout.Infinite);
        }

        public void Resume()
        {
            _t.Change(0, 1000);
        }

        public void Start()
        {
            _t.Change(0, 1000);
        }

        private void TimerTick(object state)
        {
            if (_tickExecuting)
                return;
            _tickExecuting = true;
            try
            {
                OnTick(this, EventArgs.Empty);

            }
            catch (Exception ex)
            {
                //TODO: Something more sentient about exceptions occuring whilest invoking event delegate
            }
            finally
            {
                _tickExecuting = false;
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }

        protected void Dispose(bool disposing)
        {
            if (!disposing)
                return;
            if (_t != null)
            {
                _t.Dispose();
                _t = null;
            }
        }
    }
}
 
Share this answer
 
Put a semaphore in there. Then just set the semaphore from elsewhere. For example, a simple public boolean property that is normally false. In the foreach loop above, if the value of the boolean is false, then the code proceeds as normal. If the boolean is true, it pauses. You might implement this as:

C#
foreach( XElement..... )
{
  //...
  while( this.Semaphore ) Thread.Sleep(5); // Pause is here when Semaphore == true
  //..
}


Then, where you want to pause, just set the semaphore when you want it paused. For example, if you have an event handler on a button labelled "Pause", when the event fires, check the semaphore. If it's false, then set it to true and change the button text to "Resume". If it's true, then change it to false and set the button text to "Pause". Something like this:

C#
protected void MyButton_ClickEvent( object sender, EventArgs e)
{
   myThread.Semaphore = !myThread.Semaphore; // Toggle semaphore

   // Update button to reflect what it will do next
   if( myThread.Semaphore ) ( (Button)sender ).Text = "Resume";
   else ( (Button)sender ).Text = "Pause";
}


Boom. Problem solved. If you have a whole bunch of threads, then just extend the idea. Maybe have a list of the threads running with checkboxes next to each that set/clear the semaphore for that particular thread so you can pause/resume specific threads at will, or just have one button pause/resume everything. Whatever you need.
 
Share this answer
 
Comments
StackQ 29-Nov-16 5:26am    
First thanks for your solution.
I am new to c#, so not aware with threading,as my main skill is SQL Server. Could you please help a bit more here how to declare myThread and so on?

Actual button from where I am processing whole work:-
private void btnNext_Click(object sender, EventArgs e)
{
OpenFileDialog opn = new OpenFileDialog();
opn.InitialDirectory = "C:\\";
opn.Filter = "xml files(*.xml)|*.xml";
if(opn.ShowDialog()==DialogResult.OK)
{
string str = opn.SafeFileName;
//string str = "C:\\TextReader\\";
XMLReaders(opn.FileName.Replace(str,""), opn.FileName); //Doing my work, it's definition is above in my main question
}
}

I want to Pause/Resume loop exist in above function:- XMLReaders(), which started by another button's click event, from here (below click event of button):-
private void btnPR_Click(object sender, EventArgs e)
{

}

However I am trying to implement your solution, but will appreciate your help (will be easier for me :)

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