private static void ConsumerMethod()
        {
            // Consumer method takes data from the blocking collection and writes it to a SQLite Database
            DataRecord    data;
            SQLiteCommand cmd = conn.CreateCommand();
            // Using transactions dramatically speeds up writing to SQLite
            SQLiteTransaction tr = conn.BeginTransaction();

            cmd.Transaction = tr;
            while (true)
            {
                if (dataCollection.TryTake(out data))
                {
                    SQLite_Methods.InsertResultItem(cmd, data, TABLE_NAME);
                    recordsWritten++;
                }
                else
                {
                    Thread.Sleep(1);
                }
                if (recordsWritten % RECORDS_PER_TRANSACTION == 0)
                {
                    tr.Commit();
                    tr = conn.BeginTransaction();
                    cmd.Transaction = tr;
                }
                if (recordsWritten == TOTAL_RECORDS)
                {
                    tr.Commit();
                    tr.Dispose();
                    cmd.Dispose();
                    break;
                }
            }
        }
        static void Main(string[] args)
        {
            // Start preparation for the test
            conn = SQLite_Methods.CreateConnection("test.db");
            SQLite_Methods.CreateTableIfNotExists(conn, TABLE_NAME);
            // End preparation for the test
            // Make delegates for threads to call
            ThreadStart tProd           = new ThreadStart(ProducerMethod);
            ThreadStart tCons           = new ThreadStart(ConsumerMethod);
            Thread      producerThread  = new Thread(tProd);
            Thread      producerThread2 = new Thread(tProd);
            Thread      producerThread3 = new Thread(tProd);
            Thread      producerThread4 = new Thread(tProd);
            Thread      consumerThread  = new Thread(tCons);

            // Timing C# is affected by the garbage collector. These calls negate that.
            GC.Collect();
            GC.WaitForPendingFinalizers();
            // Timing C# is affected by the processor switching between other processes on the systems.
            // This call negates that.
            TimeSpan startingTime;
            TimeSpan duration;

            startingTime = Process.GetCurrentProcess().Threads[0].UserProcessorTime;

            // DEMONSTRATE DIFFERENCE BETWEEN ONE AND FOUR PRODUCER THREADS BY COMMENTING OR UNCOMMENTING THE
            // producerThread2.Start(), producerThread3.Start(), and producerThread4.Start() LINES.
            producerThread.Start();
            producerThread2.Start();
            producerThread3.Start();
            producerThread4.Start();

            // ONLY ONE CONSUMER THREAD AT A TIME
            consumerThread.Start();
            while (true)
            {
                if (producerThread.ThreadState == System.Threading.ThreadState.Stopped && consumerThread.ThreadState == System.Threading.ThreadState.Stopped)
                {
                    duration = Process.GetCurrentProcess().Threads[0].UserProcessorTime.Subtract(startingTime);
                    Console.WriteLine($"Time taken for writing {TOTAL_RECORDS} to SQLite = {duration.TotalMinutes} minutes");
                    break;
                }
            }
        }