生产者 - 消费者模式中的线程化

时间:2014-05-29 23:05:49

标签: c# multithreading linq

首先抱歉我的英语不好。我已将此代码用于读取.csv文件,一个接一个地阅读后,它将被删除。 .csv文件格式如下:

ID     Name     ParentID
------------------------
0      [Root]    
1      A        0
2      B        0
3      C        1
4      D        2

,结果将是

[Root]
_A
__C
_B
__D

就像树一样。但我只能在1个文件上执行,并且在第一次之后,消费者再也不会醒来,所以请帮我解决这个问题或者解释如何调用这个原因以及修复方法。

非常感谢。

class Program
{
    static ProducerConsumer PrdCos;
    static string[] file;

    static void Main(string[] args)
    {
        string directory = "";
        PrdCos = new ProducerConsumer();

        Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
        directory = Input_directory();
        file = null;

        while (true)
        {
            if (Check_exist(directory) == true)
                break;
            else 
            {
                Console.WriteLine("Please Reinput \n");
                directory = Input_directory();
            }
        }

        file = Directory.GetFiles(directory, "*.csv");

        Console.WriteLine("\n-------------------------Program Start------------------------------");

        Thread thread =  new Thread(new ThreadStart(consumeJob));
        Thread thread2 = new Thread(new ThreadStart(procedureJob));
        thread.IsBackground = true;
        thread2.IsBackground = true;
        thread.Start();
        thread2.Start();

        //delete file

        //for (int i = 0; i < file.Length; i++)
        //    File.Delete(file[i]);
        Console.ReadLine();

        while(Console.ReadKey(true).Key == ConsoleKey.Enter)
        {
            Console.WriteLine("press ctr + c to exit");
        }
    }

    static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e){}

    static void procedureJob()
    {
        if (file.Length > 0)
        {
            foreach (string str in file)
            {
                PrdCos.Produce(str);
                Thread.Sleep(1000);
            }
        }
    }

    static void consumeJob()
    {
        List<string> a = new List<string>();
        a = file.ToList();
        //for(int i = 0; i<a.Count;i++)
        //{
            PrdCos.Consume();
            Thread.Sleep(100);
        //}
    }

    static string Input_directory()
    {
        string str = ""; 
        Console.Write("Input file Directory:  ");
        str = Console.ReadLine();
        return str;
    }

    static bool Check_exist(string path)
    {
        int Count;
        string[] file;
        //string fileName = "";
        string filePath;
        filePath = path;

        if (Directory.Exists(filePath) != true)                 // Check file path exist
        {
            Console.WriteLine("{0} is not valid Directory!!!", path);
            return false;
        }
        else
        {
            Count = Directory.GetFiles(filePath, "*").Length;
            file = Directory.GetFiles(filePath, "*.csv");
        }

        if (Count == 0)
        {
            Console.WriteLine("Folder is Empty!!!");
            return false;
        }
        if (Count > 0 && file.Length == 0)
        {
            Console.WriteLine("Input File not Valid!!!");
            return false;
        }
        return true;
    }

    }

    public class ProducerConsumer
    {
    Queue queue = new Queue();
    object locker = new object();
    int node = 0;
    int NODE = 0;

    public void Produce(string path)
    {
        Console.WriteLine("Processing Produce");

            lock (locker)
            {
                try
                {
                    //foreach (string mPath in path)
                    //{
                    var reader = new StreamReader(File.OpenRead(path));
                    System.Collections.Generic.List<string> Str1 = new System.Collections.Generic.List<string>();

                    while (!reader.EndOfStream)
                    {
                        string line = reader.ReadLine();
                        if (line.Split(',').Length > 3)
                        {
                            Console.WriteLine("File's Data Is Wrong Format!!!");
                            return;
                        }
                        Str1.Add(line);
                    }
                    reader.Close();
                    queue.Enqueue(Str1);
                    Thread.Sleep(2000);
                    //}
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }
        Console.WriteLine("Finished Processing Produce");
    }

    public void Consume()
    {
        Console.WriteLine("Processing Consume");
        List<string> ParentId = new List<string>();
        DataRow[] row = { };
        lock (locker)
        {
            try
            {
                if (queue.Count > 0)
                {
                    foreach (System.Collections.Generic.List<string> str in queue)
                    {
                        try
                        {
                            node = 0;
                            NODE = 0;
                            NODE = str.Count() - 1;
                            PrintData(str, 0, str);
                            Console.WriteLine("\n");
                        }
                        catch (Exception ex)
                        {
                            Console.Write(ex);
                        }

                    }
                    Console.WriteLine("Finished Processing Consume");
                    Thread.Sleep(1000);
                }
            }                
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            //while (queue.Count == 0)
            //{
            //    Monitor.Wait(locker);
            //    queue.Dequeue();
            //}
            //if (queue == null)
            //    return;
            //Thread.Sleep(100);
        }
    }

    private void PrintWithIndent(string value, int indent)
    {
        node++;
        Console.WriteLine("{0}{1}", new string(' ', indent), value);// prtValue[1]);
    }

    public void PrintData(List<string> Str, int indent, List<string> StrMain)
    {


        List<string> child = new List<string>();
        string[] Value = null;
        string[] ValueMain = null;
        for (int i = 0; i < Str.Count; i++)
        {
            if (node >= NODE)
                return;
            child = new List<string>();
            ValueMain = Str[i].Split(',');
            if (Str[i].ToString() == StrMain[0].ToString())
                continue;
            else
                PrintWithIndent(ValueMain[1], indent);
            foreach (string mStr in StrMain)
            {
                Value = mStr.Split(',');
                if (Value[2] == ValueMain[0])
                    child.Add(mStr);
            }

            child = child.OrderBy(x => (x.Split(',')[1])).ToList();    //Sort by Alphabet

            if (child.Count > 0)
            {
                PrintData(child, indent + 1, StrMain);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我注意到的第一个问题是你的消费者正在结束。虽然有更多的问题 - 我建议你扔掉它然后重新开始。

首先,您需要确保正确理解模式。然后,您需要将经典模式与.Net中的线程相关联。

一旦你理解了概念级别的东西,你还应该调查Parallel LINQ (PLINQ)Task Parallel Library (TPL) - 为你的生产者/消费者使用这些将节省大量的时间和错误(不再锁定,你可以有线程在等待时阻塞等等。)。

以下是其他一些可能有用的参考资料: