多线程和分配数组到c中的每个线程#

问题描述:

我正在编写向多个用户发送电子邮件的代码。我必须根据用户信息更换邮件内容。由于用户数量很大,我想要多个线程发送邮件来修复用户数量。所以我想创建线程并为每个线程分配一个指定用户信息的数组。我该怎么做?多线程和分配数组到c中的每个线程#

int noOfThread = noOfUsers/5000; 
    private IList<Thread> threadList = new List<Thread>(); 
    for(int i=0; i<noOfThread; i++) 
    { 
     Thread thread = new thread(FunctionToCall); 
     thread.IsBackground = true; 
     thread.Name = threadSendMail + i; 
     threadList.Add(thread); 
     thread.Start(); 
    } 

如何分配数组到每个线程并传递给函数FunctionToCall()?

+0

为什么不使用[异步API](http://msdn.microsoft.com/en-us/library/hh193922%28v=vs.110%29.aspx)发送邮件。所以你甚至不需要任何线程? – 2014-10-08 11:47:57

+0

作为一个方面说明,你不需要每个邮件的线程,这将有利地扩展。你为什么不将所需的数组传递给方法? – 2014-10-08 11:49:11

+0

Sriram Sakthivel我正在使用SendGrid发送邮件。所以我不认为异步API会起作用 – Ami 2014-10-08 11:57:49

我的建议是,在所有不使用线程现在是过时与TPL(任务并行库)的地方,你的代码必须是这样的:

Parallel.Foreach(UserList, user => 
{ 
// Do Email send action here, you can modify details per user here 
} 
); 

Parallel.For(0, noOfThread, user => 
    { 
    // Do Email send action here, you can modify details per user here 
    } 
    ); 

好处是巨大的:

  • 它会做CPU核心优化,并将分配基于可用性TY。它会根据环境/逻辑内核等进行运行时优化。

  • 您不需要根据上面的静态公式决定创建线程的数量,这不会导致任何优化,并且会像一个尺寸适合所有

    int noOfThread = noOfUsers/5000; 
    

即使你想申请然后一些这样的公式在Environment.ProcessorCount这将按照系统中的处理器数量变化带来的,但仍然它不是运行时优化和可用性。

  • 并行API在内部使用ThreadPool,这对于这样的场景来说更好,因为线程是一个昂贵的资源,并且您希望它们从池中重用,而不是创建和销毁。每个线程的默认堆栈分配为1 MB,并且您不希望内存只分配和销毁,而不能通过池重用。
+0

我认为这有时会造成问题。当两个处理器都空闲时,两个处理器都准备发送邮件,但在某些情况下,两个处理器同时占用同一用户。这怎么处理? – Ami 2014-10-10 04:46:36

+0

问题将与您的代码,并行不会做那件事,我的猜测是,你会被修改平行块(动作代表)内的共享资源,而这也正是它会导致异常,直到除非你同步。让我们假设你要添加一些值来共同清单,所有用户的块里面,现在这个名单不是线程安全的,并会导致异常,直到除非你锁定或使用并发的API。粘贴你的代码以获取更多的见解 – 2014-10-10 05:36:06

+0

代码: for(int i = 0; i { 串investarId = datatable.Rows [eachUser] [ “usrid”]的ToString(); CreateEmailLog( “用户选择:” + investarId + “迭代:” + eachUser); 串InvEmail = datatable.Rows [eachUser] [ “电子邮件”]的ToString(); // 邮件发送功能调用.. }); 我在日志文件中得到: 10/10/2014 9:32:00 AM用户选择:test77迭代:16 10/10/2014 9:32:00 AM用户选择:test77迭代:0 – Ami 2014-10-10 05:55:13

也许在这种情况下,您可以使用BlockingCollection?

例如

_collection = new BlockingCollection<List<UserInfo>>(); //BlockingCollection contains list of 5000 user for example 

var consumer = Task.Factory.StartNew(() => 
{ 
    Parallel.ForEach(Partitioner.Create(_collection.GetConsumingEnumerable()), new ParallelOptions() { MaxDegreeOfParallelism = 10}, (partOfCollection) => 
    { 
     DoSomethingWithList(partOfCollection); //in this function you loop the list of userinfo and run the 'FunctionToCall' method 
    } 
} 

//Add users in blocks of 5000 to the collection 
_collection.Add(firstPartOfUserInfo); 
_collection.Add(secondPartOfUserInfo); 

_collection.CompleteAdding(); 

consumer.Wait(); 

我不知道如果我写到这里的代码会为你工作,但是这是我使用在多个不同线程块巨大的名单。

+0

这是一个有趣的方式,在这种方式中,您将Task和Parallel API混合到Async操作中,并将块中的使用者添加到线程安全集合中。但是在我看来,这会对性能产生影响,由于阻塞收集,如果并行进程在下一个块被添加到集合之前完成,可能会出现这种情况,如果并行进程没有完成,则可能会出现这种情况。数量不大,但很可能少数。而且它会限制CPU的优化 – 2014-10-08 12:40:55

+0

的确不错,但他要求对多线程的,所以我给他看它是如何可能的:)。事实上,这将需要更多的CPU,但如果你想赢得一些时间,这是正常的。 – 2014-10-08 12:47:44