locked
How can I pause/resume a thread ? RRS feed

  • Question

  • This is a class that search for files using thread.

    The start and stop are working fine but I want also to add a pause/resume.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using System.IO;
    
    
    
    namespace FileSearcher
    {
        public class Searcher
        {
            // ----- Asynchronous Events -----
    
            public delegate void FoundInfoEventHandler(FoundInfoEventArgs e);
            public static event FoundInfoEventHandler FoundInfo;
    
            public delegate void ThreadEndedEventHandler(ThreadEndedEventArgs e);
            public static event ThreadEndedEventHandler ThreadEnded;
    
    
            // ----- Variables -----
    
            private static Thread m_thread = null;
            private static Boolean m_stop = false;
            private static SearcherParams m_pars = null;
            private static Byte[] m_containingBytes = null;
            public static ManualResetEvent _mrsevent = new ManualResetEvent(false);
    
            // ----- Public Methods -----
    
            public static Boolean Start(SearcherParams pars)
            {
                Boolean success = false;
    
                if (m_thread == null)
                {
                    // Perform a reset of all variables,
                    // to ensure that the state of the searcher is the same on every new start:
                    ResetVariables();
    
                    // Remember the parameters:
                    m_pars = pars;
    
                    // Start searching for FileSystemInfos that match the parameters:
                    m_thread = new Thread(new ThreadStart(SearchThread));
                    m_thread.Start();
                    
                    success = true;
                }
    
                return success;
            }
    
            public static void Stop()
            {
                // Stop the thread by setting a flag:
                m_stop = true;
            }
    
    
            // ----- Private Methods -----
    
            private static void ResetVariables()
            {
                m_thread = null;
                m_stop = false;
                m_pars = null;
                m_containingBytes = null;
            }
    
            private static void SearchThread()
            {
                Boolean success = true;
                String errorMsg = "";
    
                // Search for FileSystemInfos that match the parameters:
                if ((m_pars.SearchDir.Length >= 3) && (Directory.Exists(m_pars.SearchDir)))
                {
                    if (m_pars.FileNames.Count > 0)
                    {
                        // Convert the string to search for into bytes if necessary:
                        if (m_pars.ContainingChecked)
                        {
                            if (m_pars.ContainingText != "")
                            {
                                try
                                {
                                    m_containingBytes = m_pars.Encoding.GetBytes(m_pars.ContainingText);
                                }
                                catch (Exception)
                                {
                                    success = false;
                                    errorMsg = "The string\r\n" + m_pars.ContainingText + "\r\ncannot be converted into bytes.";
                                }
                            }
                            else
                            {
                                success = false;
                                errorMsg = "The string to search for must not be empty.";
                            }
                        }
    
                        if (success)
                        {
                            // Get the directory info for the search directory:
                            DirectoryInfo dirInfo = null;
                            try
                            {
                                dirInfo = new DirectoryInfo(m_pars.SearchDir);
                            }
                            catch (Exception ex)
                            {
                                success = false;
                                errorMsg = ex.Message;
                            }
    
                            if (success)
                            {
                                // Search the directory (maybe recursively),
                                // and raise events if something was found:
                                SearchDirectory(dirInfo);
                            }
                        }
                    }
                    else
                    {
                        success = false;
                        errorMsg = "Please enter one or more filenames to search for.";
                    }
                }
                else
                {
                    success = false;
                    errorMsg = "The directory\r\n" + m_pars.SearchDir + "\r\ndoes not exist.";
                }
    
                // Remember the thread has ended:
                m_thread = null;
    
                // Raise an event:
                if (ThreadEnded != null)
                {
                    ThreadEnded(new ThreadEndedEventArgs(success, errorMsg));
                }
            }
    
            private static void SearchDirectory(DirectoryInfo dirInfo)
            {
                if (!m_stop)
                {
                    try
                    {
                        foreach (String fileName in m_pars.FileNames)
                        {
                            FileSystemInfo[] infos = dirInfo.GetFileSystemInfos(fileName);
    
                            foreach (FileSystemInfo info in infos)
                            {
                                if (m_stop)
                                {
                                    break;
                                }
    
                                if (MatchesRestrictions(info))
                                {
                                    // We have found a matching FileSystemInfo, so let's raise an event:
                                    if (FoundInfo != null)
                                    {
                                        FoundInfo(new FoundInfoEventArgs(info));
                                    }
                                }
                            }
                        }
    
                        if (m_pars.IncludeSubDirsChecked)
                        {
                            DirectoryInfo[] subDirInfos = dirInfo.GetDirectories();
                            foreach (DirectoryInfo subDirInfo in subDirInfos)
                            {
                                if (m_stop)
                                {
                                    break;
                                }
    
                                // Recursion:
                                SearchDirectory(subDirInfo);
                            }
                        }
                    }
                    catch (Exception)
                    {
                    }
                }
            }
    
            private static Boolean MatchesRestrictions(FileSystemInfo info)
            {
                Boolean matches = true;
    
                if (matches && m_pars.NewerThanChecked)
                {
                    matches = (info.LastWriteTime >= m_pars.NewerThanDateTime);
                }
    
                if (matches && m_pars.OlderThanChecked)
                {
                    matches = (info.LastWriteTime <= m_pars.OlderThanDateTime);
                }
    
                if (matches && m_pars.ContainingChecked)
                {
                    matches = false;
                    if (info is FileInfo)
                    {
                        matches = FileContainsBytes(info.FullName, m_containingBytes);
                    }
                }
    
                return matches;
            }
    
            private static Boolean FileContainsBytes(String path, Byte[] compare)
            {
                Boolean contains = false;
    
                Int32 blockSize = 4096;
                if ((compare.Length >= 1) && (compare.Length <= blockSize))
                {
                    Byte[] block = new Byte[compare.Length - 1 + blockSize];
    
                    try
                    {
                        FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
    
                        // Read the first bytes from the file into "block":
                        Int32 bytesRead = fs.Read(block, 0, block.Length);
    
                        do
                        {
                            // Search "block" for the sequence "compare":
                            Int32 endPos = bytesRead - compare.Length + 1;
                            for (Int32 i = 0; i < endPos; i++)
                            {
                                // Read "compare.Length" bytes at position "i" from the buffer,
                                // and compare them with "compare":
                                Int32 j;
                                for (j = 0; j < compare.Length; j++)
                                {
                                    if (block[i + j] != compare[j])
                                    {
                                        break;
                                    }
                                }
    
                                if (j == compare.Length)
                                {
                                    // "block" contains the sequence "compare":
                                    contains = true;
                                    break;
                                }
                            }
    
                            // Search completed?
                            if (contains || (fs.Position >= fs.Length))
                            {
                                break;
                            }
                            else
                            {
                                // Copy the last "compare.Length - 1" bytes to the beginning of "block":
                                for (Int32 i = 0; i < (compare.Length - 1); i++)
                                {
                                    block[i] = block[blockSize + i];
                                }
    
                                // Read the next "blockSize" bytes into "block":
                                bytesRead = compare.Length - 1 + fs.Read(block, compare.Length - 1, blockSize);
                            }
                        }
                        while (!m_stop);
    
                        fs.Close();
                    }
                    catch (Exception)
                    {
                    }
                }
    
                return contains;
            }
        }
    }

    I added the variable _mrsevent and made it public static but I'm not sure where and how to use it in the Searcher class.

    In form1 I added a pause button click event and I want that the first click will pause the thread and another click will resume the thread.

    private void pauseButton_Click(object sender, EventArgs e)
            {
                Searcher._mrsevent.Reset();
            }


    Friday, May 29, 2020 8:50 PM

All replies

  • Hello,

     Do I understand your request correctly, "You want to pause/resume an active Thread"?

    If this is your intention then are various ways to accomplish this. Here is a possible

    solution, which may/may not satisfy your project needs;

     Example of Quick and Dirty

    1. Declare/assign private bool pauseFlag to false within scope class Searcher.

    2. Inside the Button click event, toggle the state, code pauseFlag ^= true

    3. Inside SearchThread or SearchDirectory methods, include the following code;

    while( pauseFlag == true);

     Depending on when you want to allow a pause/resume is determined by the

    placement of the above code in your chain of events but must occur in a loop.

     

     Synopsis

    When you click the button, the button event executes the code to toggle

    the state of pauseFlag.  The above While conditional code creates a loop that only

    ends when the state of pauseFlag is false.  Essentially pause the current method.

     

     Quick and dirty sometimes works but its not proper practice. I refer you to the following

    link for the more proper; Synchronization

     

     Hope this helps :)

    Sunday, May 31, 2020 3:58 AM