Mohamed Adel Ismail
Mohamed Adel Ismail

Reputation: 11

use multithread to write into text files using C#

Hope you can help me with this one.i am beginner in multithreading programming with C#.

I am trying to build a program to write all numbers from range 1 to 2000 in two text files using two threads.

Every thread should write number from 1 to 2000 that not found at any of the two files "there is no duplicated numbers in the files" and every thread should't write the number that have been wrote by the another thread.

At the end if we merged the numbers of the two files we should have the numbers from 1 to 2000

Here is the source code i am trying but there is a problem in the writing for loop in the below image

i can't handle the process of writing by the two synchronized threads and i had exception:

Object synchronization method was called from an unsynchronized block of code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;

namespace Multithreading
{
    class Program
    {

       static TextWriter file2 = new StreamWriter("file2 location");
       static TextWriter file1 = new StreamWriter("file1 location");

       static void Main(string[] args)
       {
           try
           {
               int[] array = new int[2000];
               Thread thread1 = new Thread(Program.writeinfile1);
               Thread thread2 = new Thread(Program.writeinfile2);

               for (int counter = 1; counter <= 2000; counter++)
               {
                   thread1.Start(counter);
                   thread2.Start(++counter);
                   Monitor.Enter(thread1);
                   Monitor.Wait(thread1);
                   Monitor.PulseAll(thread2);
               }
           }
           catch (FileNotFoundException)
           {
               Console.WriteLine("the file you are trying to open is not found");
           }
       }

       public static void writeinfile1(object x)
       {
           int converttointx = (int)x;
           file1.WriteLine(converttointx);
           file1.Close();
       }

       public static void writeinfile2(object y)
       {
           int converttointy = (int)y;
           file2.WriteLine(converttointy);
           file2.Close();
       }
    }
}

Upvotes: 0

Views: 638

Answers (2)

Adrian Sanguineti
Adrian Sanguineti

Reputation: 2505

You are not using the Monitor class correctly. The call to Monitor.PulseAll(thread2); should be called within thread the thread which owns the lock, which in this case would be within the writeinfile1 and writeinfile2 method.

This is why you are getting the exception:

Object synchronization method was called from an unsynchronized block of code.

See the following StackOverflow question for the correct way to use Monitor.PulseAll(object):

Upvotes: 0

JohnLBevan
JohnLBevan

Reputation: 24470

Here's an example of multi-threaded calls talking to one another to ensure they don't duplicate work. I've not done exactly what you've asked for, since this looks quite homeworky; but hopefully this will help you to figure out the solution to your issue...

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace StackOverflow
{
    class Program
    {
        static void Main(string[] args)
        {
            new Program();
            Console.WriteLine("done");
            Console.ReadKey();
        }
        Program()
        {
            int noThreads = 5;
            int target = 2000;
            StartThread(noThreads, target);
        }

        //kicks off our threads / waits for all threads to complete before returning
        void StartThread(int noThreads, int target)
        {
            int id = noThreads--;
            if (id > 0)
            {
                Doer doer = new Doer(id, target);
                Thread t = new Thread(doer.Do);
                t.Start();
                StartThread(noThreads,target);
                t.Join();
            }
        }


    }

    class Doer 
    {
        static int marker = 0;
        static readonly object syncLocker = new object();
        readonly int id;
        readonly int target;

        public Doer(int id, int target)
        {
            this.id = id;
            this.target = target;
        }

        public void Do() 
        {
            while (marker < this.target)
            {
                int i;
                lock (syncLocker)
                {
                    i = ++marker;
                }
                System.Console.WriteLine("{0:00}: {1:###0}", id, i);
                //Thread.Sleep(RandomNo()); //uncomment this & code below if your threads are taking turns / behaving too predictably
            }
        }


        /*
        static readonly Random rnd = new Random();
        static readonly object rndSyncLocker = new object();
        public static int RandomNo()
        {
            lock (rndSyncLocker)
            {
                return rnd.Next(0, 1000); 
            }
        }
        */

    }
}

Upvotes: 2

Related Questions