Search code examples
c#multithreadingbackground-process

How to create and use background thread to change object from another thread


I have object in main thread. I need to create background thread, which will parse website permanently and change object from main thread each time background thread gets new data. What is the proper way to do that? Another question: how to create background thread which will work permanently?

I need smth like

static Main void() {
  Object VariableObject = new Object();
  //TODO: CreateBackgroundThread ();
  //TODO: DoForegroundWork();
}

...
CreateBackgroundThread void () {
  while (true) {
    Object NewData = new Object;
    //TODO: Get object from Main method and assign NewData object to it
  }
}

I hope I expressed clear. I suppose it's ordinary task for many projects, I just don't know how to do it.


Solution

  • A background thread is scoped to the main thread. So it'll run as long as the console app is alive. .Net has a rich threading library, so I leave it up to you.

    for ex) 1) use a delegate and call BeginInvoke 2) system.threading.Thread namespace 3) System.Threading.Tasks namespace

    Since threading can be daunting, here's a sample console app that should do almost what you need.

    run the app and once your comfy with the basics, you can write your own.

    using System;
    using System.Collections.Generic;
    using System.Threading;
    
    /// <summary>
    /// Represent a hard working employee.
    /// 
    /// The employee will process a job, once it comes in.
    /// 
    /// 
    /// </summary>
    public class Employee
    {
        private Queue<string> _tasksTray;
        private string _employeeID;
    
        public Employee(string employeeID, Queue<string> taskTray)
        {
            //employee's ID number.  
            this._employeeID = employeeID;
    
            //get a reference to the task tray
            this._tasksTray = taskTray;
    
            //fire up a worker thread
            var thread = new Thread(new ThreadStart(this.Run));
            thread.IsBackground = true;
            thread.Start();
        }
    
        private void Run()
        {
            string myTask = null;
    
            //time to work until i die
            while (true)
            {
                //discard the old task, if any
                myTask = string.Empty;
    
                //check if we have anything to do
                if (this._tasksTray.Count == 0)
                {
                    lock (this._tasksTray)
                    {
                        //no jobs; time to chill.
                        Console.WriteLine("Employee# {0} is taking a break.", this._employeeID);
                        Monitor.Wait(this._tasksTray);
                    }
                }
    
                //work finally came in. Grab the tray and get a task.
                lock (this._tasksTray)
                {
                    if (this._tasksTray.Count > 0)
                    {
                        //yes, i got a job. Remove the task from the tray, so no one else can get it.
                        myTask = this._tasksTray.Dequeue();
                    }
                }
    
                //time to process the task
                if (!string.IsNullOrEmpty(myTask))
                {
                    Console.WriteLine("Employee# {0} has completed job: {1}.", this._employeeID, myTask);
                    Thread.Sleep(1000);
                }
            }
        }
    }
    
    /// <summary>
    /// Represent your standard manager that manages a tray of jobs.
    ///  
    /// for ex)
    /// 1) he has a certain number of employees.
    /// 2) he interacts with clients and get jobs
    /// 3) he post jobs to JIRA and notifies his employees to start working.
    /// </summary>
    public class Manager
    {
        private Queue<string> _taskTray;
        private List<Employee> _employees;
    
        public Manager(int numOfEmployees = 5)
        {
            //Tray of jobs. This is a shared resource between the manager and employees, so we have to make sure only one person access it at any time.
            this._taskTray = new Queue<string>();
    
            //set employees
            this._employees = new List<Employee>();
            for (var i = 0; i < numOfEmployees; i++)
            {
                this._employees.Add(new Employee(i.ToString(), this._taskTray));
            }
        }
    
        public void AddTask(params string[] newTasks)
        {
            lock (this._taskTray)
            {
                //add new tasks to the tray
                foreach (var task in newTasks)
                {
                    this._taskTray.Enqueue(task);
                }
    
    
                //break time over. time to get back to work.
                Console.WriteLine("\nManager said: Wake up. Time to work. We got {0} jobs.\n", newTasks.Length);
                Monitor.PulseAll(this._taskTray);
            }
        }
    
    }
    
    
    //Main
    class Program
    {
    
        static void Main(string[] args)
        {
            try
            {
                //create a manager
                var manager = new Manager(3);
    
                //add jobs
                manager.AddTask("Task 1", "task 2");
    
                //simulate downtime
                Thread.Sleep(5000);
    
                //add more jobs
                var jobs = new List<string>();
                for (int i = 0; i < 10; i++)
                {
                    jobs.Add("Project# " + i.ToString());
                }
                manager.AddTask(jobs.ToArray());
    
            }
            catch (Exception ex)
            {
    
                Console.WriteLine(ex.Message);
            }
    
            Console.WriteLine("press any key to end the program.");
            Console.Read();
        }
    
    
    }