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
}
}
}
}