0

I have two task which work as producer and consumer, but they don't run in parallel. Second one waits for the first one to compelete. Can you explain why and how can I correct this? I want both of them run at the same time. (I try many varians, but all of them don't work well)

class DirectoryReader
    {
        private readonly string _dir ;
        private Processor[] _processors;
        private string[] _files;
        private readonly Regex _rx = new Regex(@"([^.\\]+)\.cs");

        private Queue<Processor> queue = new Queue<Processor>();
        private bool isOff;
        private AutoResetEvent isAvailable = new AutoResetEvent(false);
        private StreamWriter log = new StreamWriter("Log.txt");



        public DirectoryReader(string dir)
        {
            _dir = dir; 
        }

        public Container[] ProcessAllFiles()
        {
            _files = Directory.GetFiles(_dir, "*.cs", SearchOption.AllDirectories);
            _processors = new Processor[_files.Length];                   

            var thread = Task.Run(() => Compute());
            var thread2 = Task.Run(() => Read());           
            thread.Wait();          
        }

        public void Read()
        {
                for (var i = 0; i < _files.Length; i++)
                {
                    try
                    {
                        var matches = _rx.Matches(_files[i]);
                        foreach (var match in matches)
                        {
                            //Console.WriteLine(match);
                            lock (log)
                            {
                                log.WriteLine(match);
                            }
                        }
                        _processors[i] = new Processor(matches[matches.Count - 1].ToString(), File.ReadAllText(_files[i]));
                        lock (queue)
                        {
                            queue.Enqueue(_processors[i]);
                            isAvailable.Set();
                        }

                    }
                    catch (IOException ex)
                    {
                        Console.WriteLine(ex.Message + _files[i]);
                    }

                }
                isOff = true;
            }

        public void Compute()
        {
            Processor proc = null;
            int ccount = 0;
            while (true)
            {
                lock (queue)
                {
                    if ((ccount = queue.Count) > 0)
                    {
                        proc = queue.Dequeue();
                    }
                }
                if (ccount == 0)
                {
                    if (isOff)
                    {
                        return;
                    }
                    else
                    {
                        isAvailable.WaitOne();
                    }
                }
                if (proc != null)
                {
                    //Some calculations on proc
                    lock (log)
                    {
                        log.WriteLine("+++++" + proc.FileName);
                    }
                }

            }
        }
    }

UPD1: I rewrite this code with using BlockingCollection, but is still doesn't work correct

class DirectoryReader
    {
        private readonly string _dir ;
        private Processor[] _processors;
        private string[] _files;
        private readonly Regex _rx = new Regex(@"([^.\\]+)\.cs");
        private List<Container> answer = new List<Container>();       
        BlockingCollection<FileContainer> dataItems = new BlockingCollection<FileContainer>();

        public DirectoryReader(string dir)
        {
            _dir = dir; 
        }

        public void ProcessAllFiles()
        {
            _files = Directory.GetFiles(_dir, "*.cs", SearchOption.AllDirectories);
            _processors = new Processor[_files.Length];

            var task = Task.Factory.StartNew(Compute);
            var task2 = Task.Factory.StartNew(Read);
            Task.WaitAll(task, task2);
        }

        public void Read()
        {
            for (var i = 0; i < _files.Length; i++)
            {
                try
                {
                    var matches = _rx.Matches(_files[i]);                                          
                    dataItems.Add(new FileContainer{
                        Name = matches[matches.Count - 1].ToString(),
                        Content = File.ReadAllText(_files[i])});                       
                }
                catch (IOException ex)
                {
                    Console.WriteLine(ex.Message + _files[i]);
                }

            }
            dataItems.CompleteAdding();
        }

        public void Compute()
        {
            FileContainer proc = null;
            while (!dataItems.IsCompleted)
            {
                try
                {
                    proc = dataItems.Take();
                }
                catch (InvalidOperationException) { }
                if (proc != null)
                {
                    //Some calculations
                }
            }
        }
    }
beta-tank
  • 390
  • 1
  • 4
  • 17
  • if I am not mistaking you need to change isAvailable.Set(); to isAvailable.ReSet(); In order to set the lock as blocking you should use Reset and not Set. – Koby Yehezkel Apr 06 '14 at 09:27
  • Not trying to analyze what's wrong, but you rarely (if ever) need `AutoResetEvent` if you use TPL. This code needs re-factoring. Consider using `TaskCompletionSource` and `BlockingCollection` for your producer-consumer scenarios. One step further would be to use TPL Dataflow. – noseratio Apr 06 '14 at 11:09
  • @KobyYehezkel I tried to use `isAvailable.Reset()` instead of `isAvailable.Set()`, it didn't help me – beta-tank Apr 06 '14 at 11:45
  • @Noseratio I rewrite my code with using `BlockingCollection`, but is still doesn't work correct – beta-tank Apr 06 '14 at 13:09
  • How exactly are you observing whether they run in parallel? – svick Apr 06 '14 at 13:15
  • @svick I write logs in which task, and strings from first task stay upper then strings from second tasks – beta-tank Apr 06 '14 at 13:20

0 Answers0