将每个列表项逐一传递给一个新线程



我想做的非常简单,
我扫描一个字符串列表,然后将每个字符串传递给一个新的线程进行打印。

using System;
using System.Collections.Generic;
using System.Threading;
namespace MultithreadingSynchronization
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> stringList = new List<string> { "server1", "server2", "server3", "server4", "server5", "server6", "server7", "server8", "server9"};
            foreach (string server in stringList)
            {
                ThreadStart work = delegate { Threadjob(server); };
                new Thread(work).Start();
                //Thread.Sleep(10); // 10 ms delay of main thread
            }
        }
        public static void Threadjob(object server)
        {
            Console.WriteLine(server);
        }
    }
}

由于某种原因,有些线程接收到了错误的值,因此,输出会显示一些重复的字符串,也会错过一些字符串
我期待这个输出(订单不重要):

server1
server2
server3
server4
server5
server6
server7
server8
server9

但是,有时我会得到这个:

server3
server2
server5
server5
server7
server4
server8
server9
server9

有时我会得到这个:

server2
server2
server4
server3
server6
server7
server7
server8
server9

等等。

事实上,如果我在每个线程创建之后都设置一个延迟,我就会得到我期望得到的结果。

知道吗?

您应该制作变量的本地副本。试试这个:

    foreach (string server in stringList)
    {
        string local = server;
        ThreadStart work = delegate { Threadjob(local); };
        new Thread(work).Start();
        //Thread.Sleep(10); // 10 ms delay of main thread
    }

这里的更多信息:在C#中捕获循环中的变量

new Thread(Threadjob).Start(server);

完成!但是,使用任务而不是线程可能更可取,或者至少使用ThreadPool。

好吧,我想我明白了。
Frobeach循环保存一个指针,并在每次迭代时对其进行更改。有时,线程已经创建,但仍然没有运行。同时,循环在下一次迭代中更改指针,当线程开始其作业时,它会获得当前指针的值(后续字符串)。

顺便说一句,我在这里找到了另一个解决方案,如何将参数传递给线程的主函数,所以我修复了我的循环,它现在可以正常工作了

foreach (string server in stringList)
{
    Thread thread1 = new Thread(new ParameterizedThreadStart(Threadjob));
    thread1.Start(server); 
}

相关内容

最新更新