同时使用线程和任务

时间:2017-10-06 22:45:41

标签: c# .net multithreading c#-4.0 task

作为一个做线程和任务的新手,我在我的小练习应用程序中编写了两个线程和一个任务,如下所示:

    static List<string> myList = new List<string>();
    static void Main(string[] args)
    {
        //Run the whole operation both threads and task.
        Operation();
    }
    static async void Operation()
    {
        Task t = Task.Run(new Action(RunThreads));
        t.Wait();

        //Write the result.
        WriteMessage();
    }
    static void RunThreads()
    {
        //Read thread1.
        string threadName = "Thread-1";
        Thread thread1 = new Thread(() => DoSomething(threadName));
        thread1.Name = threadName;
        thread1.Start();

        //Read thread2.
        threadName = "Thread-2";
        Thread thread2 = new Thread(() => DoSomething(threadName));
        thread2.Name = threadName;
        thread2.Start();
    }
    public static void DoSomething(string threadName)
    {
        for (int i = 1; i < 10; i++)
        {
            myList.Add(string.Format("{0} from thread: {1}", i, threadName));
        }
    }

    private static void WriteMessage()
    {
        foreach (string val in myList)
        {
            Console.WriteLine(val);
        }
        Console.Read();
    }

我希望首先完全执行两个线程,并在&#34; myList&#34;中添加值。一旦这些线程完成(最终在这两个线程结束时,&#34; myList&#34;将包含20个项目......)然后运行&#34; WriteMessage()&#34;循环遍历所有这20个项目并在控制台中打印它们的方法。

以下是我期望在控制台中编写的输出:

  • 1 from thread:Thread-2
  • 1 from thread:Thread-1
  • 2 from thread:Thread-1
  • 2 from thread:Thread-2
  • 3 from thread:Thread-2
  • 4 from thread:Thread-2
  • 3 from thread:Thread-1
  • 5 from thread:Thread-2
  • 此列表最多可延续20项。

(我知道来自&#34; Thread-1&#34;和&#34; Thread-2&#34;的消息序列可能不同,因为该过程将是异步的但应该恰好10每个项目。)

我的实现问题是:在完成这两个线程之前,正在执行WriteMessage()方法。

3 个答案:

答案 0 :(得分:0)

  static object _lock = new object();
        static List<string> myList = new List<string>();
        TaskFactory TaskFac = new TaskFactory();


        static void Main(string[] args)
        {
            //Run the whole operation both threads and task.
            Operation();
        }
        static async void Operation()
        {
            Task t = Task.Run(new Action(RunThreads)).ContinueWith(o => {

                WriteMessage();


            });
            t.Wait();

            Console.ReadKey();

            //Write the result.
            //  WriteMessage();
        }
        static void RunThreads()
        {
            //Read thread1.
            string threadName = "Thread-1";
            Thread thread1 = new Thread(() =>
            {

                for (int i = 1; i < 11; i++)
                {
                    DoSomething(

                    threadName, i


                    );
                }

            });
            thread1.Start();

            string threadName1 = "Thread-2";
            Thread thread2 = new Thread(() => { 
             for (int i = 1; i < 11; i++)
            {
                DoSomething(

                threadName1, i


                );
            } });
            thread2.Start();



        }
        public static void DoSomething(string threadName,int loop_index)
        {
            Monitor.Enter(_lock);
            {

                    myList.Add(string.Format("{0} from thread: {1}",loop_index, threadName));

                Monitor.Exit(_lock);
            }

        }

        private static void WriteMessage()
        {
            foreach (string val in myList)
            {
                Console.WriteLine(val);
            }
            Console.Read();
        }

答案 1 :(得分:0)

我认为你要做的是让Operation void等到另外两个线程完成。我所做的是创建一个布尔值,当线程完成时它将变为true,因此让Operation继续。这适用于VS2017。在第2行,你可以看到bool,第17行是它等待的地方,第33行是布尔值被改变的地方。我目前不在我的桌面上(笔记本电脑,慢速),所以如果你有进一步的问题,我可以修改这个答案。

static List<string> myList = new List<string>();

static bool taskDone = false;

static void Main(string[] args)
{
    //Run the whole operation both threads and task.
    Operation();
}
static async void Operation()
{
    Task t = Task.Run(new Action(RunThreads));
    t.Wait();

    //Write the result.
    while(!taskDone);
    WriteMessage();
}
static void RunThreads()
{
    //Read thread1.
    string threadName = "Thread-1";
    Thread thread1 = new Thread(() => DoSomething(threadName));
    thread1.Name = threadName;
    thread1.Start();

    //Read thread2.
    threadName = "Thread-2";
    Thread thread2 = new Thread(() => DoSomething(threadName));
    thread2.Name = threadName;
    thread2.Start();

    taskDone = true;
}
public static void DoSomething(string threadName)
{
    for (int i = 1; i < 10; i++)
    {
        myList.Add(string.Format("{0} from thread: {1}", i, threadName));
    }
}

private static void WriteMessage()
{
    foreach (string val in myList)
    {
        Console.WriteLine(val);
    }
    Console.Read();
}

答案 2 :(得分:0)

您可以使用Task来实现此目的。找到下面提供的代码。传递给DoWork函数的参数是执行工作的参数。这应该从每个DoWork调用的循环动态设置。

                int numberOfProcess = 3;
                Task[] _tasks = new Task[numberOfProcess];

                for (int i = 1; i <= numberOfProcess; i++)
                {
                    string[] args = new string[2];
                    args[0] = minSlNo.ToString();
                    args[1] = nextSlno.ToString();                     

                    _tasks[i - 1] = Task.Factory.StartNew(() =>
                    {
                        //do the required work
                        DoWork(args);
                    });

                    System.Console.WriteLine("Min =" + minSlNo + "  Next Msg=" + nextSlno);
                    SetLogFilesProperty("BatchJob_Start", args[0].ToString() + "_" + args[1].ToString());                    
                }

                while (_tasks.Any(t => !t.IsCompleted)) 
                {//execution waits till all the tasks are completed  
                }

                Console.Write("All Tasks Completed"+DateTime.Now);