【问题标题】:Working with both Thread and Task at the same time同时使用线程和任务
【发布时间】:2017-10-06 22:45:41
【问题描述】:

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

    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();
    }

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

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

  • 1 来自线程:线程 2
  • 1 来自线程:线程 1
  • 2 来自线程:线程 1
  • 2 来自线程:线程 2
  • 3 来自线程:线程 2
  • 4 来自线程:线程 2
  • 3 来自线程:线程 1
  • 5 来自线程:线程 2
  • 此列表最多可包含 20 项。

(我知道来自“Thread-1”和“Thread-2”的消息顺序可能不同,因为进程将是异步的,但每个应该正好有 10 项)。

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

【问题讨论】:

  • List&lt;T&gt; 不是线程安全的!
  • 您应该等待线程完成。在RunThreads 的末尾使用thread1.Join()thread2.Join()

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


【解决方案1】:

我认为您正在尝试做的是让Operation void 等到其他两个线程完成。我所做的是创建一个布尔值,当线程完成时将变为真,因此让Operation 继续。这适用于 VS2017。在第 2 行你可以看到布尔值,第 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();
}

【讨论】:

  • 它仍然命中了 WriteMessage() 方法。
【解决方案2】:

您可以使用 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);

【讨论】:

【解决方案3】:
  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();
        }

【讨论】:

  • 在我的电脑上它工作了..你能告诉我输出中的错误信息吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-24
  • 2015-06-26
  • 2020-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多