how to suspend certain threads using EventWaitHandler

317 Views Asked by At

I have this process with two threads in it. and a form that has buttons (start, suspend, pause, resume). whenever I suspend using the EWH.WaitOne() the whole application freezes (suspends) and I can't press the resume button any more

Is there a way to suspend the 2 threads only while the form keeps on running? (thread 1 and 2 in my code)

 public partial class Form1 : Form
    {
        public static System.Timers.Timer timer;
        static Thread Thread1;
        static Thread Thread2;
        private static EventWaitHandle ewh = new EventWaitHandle(false, EventResetMode.AutoReset);


        static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            using (var writer = File.AppendText("WriteTo.txt"))
            {
                writer.AutoFlush = true;
                writer.WriteLine(e.SignalTime);
            }


        }
        static void method1()
        {
            string text = "";
            using (FileStream fs = File.Open("C:\\Users\\Wissam\\Documents\\Visual Studio 2010\\Projects\\Proc1\\Proc1\\bin\\Debug\\MyFile.txt", FileMode.Open, FileAccess.Read, FileShare.None))
            {
                int length = (int)fs.Length;
                byte[] b = new byte[length];
                UTF8Encoding temp = new UTF8Encoding(true);

                while (fs.Read(b, 0, b.Length) > 0)
                {
                    text += temp.GetString(b);
                }
                using (FileStream fs1 = File.Open("C:\\Users\\Wissam\\Documents\\Visual Studio 2010\\Projects\\Proc1\\Proc1\\bin\\Debug\\MyFile1.txt", FileMode.Open, FileAccess.Write, FileShare.None))
                {
                    fs1.Write(temp.GetBytes(text), 0, temp.GetByteCount(text));
                    Thread.Sleep(1000);
                }

            }
        }
        static void method2()
        {
            timer = new System.Timers.Timer(1000);
            timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
            timer.Interval = 1000;
            timer.Enabled = true;


        }
1

There are 1 best solutions below

0
On

Suspending threads directly is basically a risky proposition - from another thread, you can't tell when the "target" thread is in the middle of something critical. For example, you don't want to suspend a thread while it owns a lock that you'll want to acquire from another thread.

You can certainly use a wait handle - I'd suggest ManualResetEvent in this case. The controlling thread would call Set to give the green light to other threads, and Reset to "ask" them to suspend. The other threads would then call WaitOne periodically (usually as the first part of a loop), blocking when the event isn't set.

You may well want to put a time-out on the wait call, so that you can periodically check the state of other things (e.g. whether to quit completely) - it depends on your situation. Use the return value of WaitOne to find out whether the event was actually signalled, or whether you just timed out.

Another alternative would be to use Monitor.Pulse / Monitor.PulseAll / Monitor.Wait to indicate state changes, and keep a separate flag saying whether or not the thread should do work. You'd need to be careful around the memory model to check that your threads see changes written by each other though.

Given that you appear to be doing work once per second, yet another alternative - possibly simpler would be to do all the work in a timer which you simply enable and disable appropriately.