C# Pause a Thread - Wait For An Event To Happen - Continue Thread
Tags: csharp, event, manualresetevent, dotnet
Published: 2019-01-10 18:41:15

---
title: C# Pause a Thread - Wait For An Event To Happen - Continue Thread
published: true
description: How we can use ManualResetEventSlim with Task.Run to pause the execution of the tread, wait for an event to happen and resume the execution of Task.Run thread.
tags: CSharp,Event,ManualResetEvent,dotnet
---

Last week I came across a new problem that took me a while before I was able to solve it and I want to share my experience with you.

# The problem

I had a console application and one Thread was adding Jobs to a List of Jobs and another thread was iterating this list to Execute these Jobs.

```csharp
ConcurrentQueue<Job> _queue = new ConcurrentQueue<Job>();
BlockingCollection<Job> _jobs = new BlockingCollection<Job>(_queue);

 var job1 = new Job(1);
 var job2 = new Job(2);
 var job3 = new Job(3);


_jobs.Add(job1);
_jobs.Add(job2);
_jobs.Add(job3);

```

Here is a simplified version of the Job class:

```csharp
public class Job
    {
        public delegate void JobFinishedHandler(object myObject, JobFinishedArgs myArgs);
        public event JobFinishedHandler OnJobFinished;
        public int JobId { get; set; } 
        public Job(int jobId)
        {
            this.JobId = jobId;
        }

        public void Execute()
        {
            Console.WriteLine($"Executing Job {this.JobId}");
            Thread.Sleep(new Random().Next(1000, 3000));
            OnJobFinished(this, new JobFinishedArgs("Job Finished!"));
        }
    }

public class JobFinishedArgs : EventArgs
    {
        private readonly string _message;
        public string Message { get { return _message; } }

        public JobFinishedArgs(string message)
        {
            this._message = message;
        }
    }

``` 

The initial code that iterated the List of Jobs was the following:

```csharp
var thread = new Thread(() =>
            {
                while (!_jobs.IsCompleted)
                {
                    var innerThread = new Thread(() =>
                    {
                        Job job = null;
                        
                        try
                        {
                            job = _jobs.Take();
                        }
                        catch (InvalidOperationException) { }

                        job?.Execute();
                    })
                    {
                        // This is important as it allows the process to exit
                        // while this thread is running
                        IsBackground = true
                    };
                    innerThread.Start();
                }
            })
            {
                // This is important as it allows the process to exit
                // while this thread is running
                IsBackground = true
            };
            thread.Start();

```

The problem with this approach was that the jobs are executing in parallel and it means that some times job3 will finish before the previously started jobs, something I didn't want.
I needed all jobs to execute sequentially one after the other.

While I was trying to find an elegant solution to my problem I came accross **ManualResetEvent** and as [Microsoft docs](https://docs.microsoft.com/en-us/dotnet/api/system.threading.manualresetevent?view=netframework-4.7.2) says:

> Notifies one or more waiting threads that an event has occurred. This class cannot be inherited.

It was exactly what i needed.
Now i was armed with new knowledge and this is:

I will use **ManualResetEventSlim**
> Provides a slimmed down version of ManualResetEvent.

Use the constructor **ManualResetEventSlim(Boolean)**
> Initializes a new instance of the ManualResetEventSlim class with a Boolean value indicating whether to set the intial state to signaled.

In my case I will initialize it to true cause I want to immediately execute the first job

Use **Wait()** Method of **ManualResetEventSlim** inside my Task.Run iteration
> Blocks the current thread until the current ManualResetEventSlim is set.

And immediately call **Reset()** of **ManualResetEventSlim** Method
> Sets the state of the event to nonsignaled, which causes threads to block.

to stop the current Thread from executing any other Job until this one is finished first.

So I refactor the code as following:

```csharp
// Set Manual Reset Event to true cause I want to immediately 
// start executing the jobs, I don't want the tread to wait
ManualResetEventSlim _canExecute = new ManualResetEventSlim(true);
ConcurrentQueue<Job> _queue = new ConcurrentQueue<Job>();
BlockingCollection<Job> _jobs = new BlockingCollection<Job>(_queue);

```

```csharp
var thread = new Thread(() =>
            {
                while (!_jobs.IsCompleted)
                {
                    var innerThread = new Thread(() =>
                    {
                        Job job = null;
                        // Now i wait for the ManualResetEvent to be set to True
                        _canExecute.Wait();
                        //and immediatly Reset it so that the Thread will pause
                        // on the above line and again wait for the ManualResetEvent
                        // to be set to true
                        _canExecute.Reset();
                        try
                        {
                            job = _jobs.Take();
                        }
                        catch (InvalidOperationException) { }

                        job?.Execute();
                    })
                    {
                        // This is important as it allows the process to exit
                        // while this thread is running
                        IsBackground = true
                    };
                    innerThread.Start();
                }
            })
            {
                // This is important as it allows the process to exit
                // while this thread is running
                IsBackground = true
            };
            thread.Start();

```

So far with the above changes only the first Job will be executed.
In order to continue with the rest of the Jobs we need to use the **Set()** Method of **ManualResetEventSlim**
> Sets the state of the event to signaled, which allows one or more threads waiting on the event to proceed.

and we do that by subscribing to the **OnJobFinished** event and set the ManualResetEventSlim to true.

```csharp
var job1 = new Job(1);
var job2 = new Job(2);
var job3 = new Job(3);

job1.OnJobFinished += (e, s) => _canExecute.Set();
job2.OnJobFinished += (e, s) => _canExecute.Set();
job3.OnJobFinished += (e, s) => _canExecute.Set();

_jobs.Add(job1);
_jobs.Add(job2);
_jobs.Add(job3);

```
Now our List of Jobs is executing sequentially one after the other! 

You can find the full code on my [GitHub](https://github.com/Rickinio/ManualResetEventExample)

This post was written with love ❤️