smtp.SendMailAsync(message)是否在新线程中运行

时间:2014-04-10 06:45:20

标签: c# multithreading email asynchronous

异步函数是否在新线程中运行。它继续正常执行。

smtp.SendMailAsync(message);     

如果消息列表中有100条消息:msgList,我们为此设置foreach,它是否会创建100个线程并且将并行运行。

foreach (var item in msgList)
{
    smtp.SendMailAsync(item);
}

请解释我,以及表现问题 如果有更好的方法可以立即发送大量电子邮件,请告诉我。

3 个答案:

答案 0 :(得分:0)

首先,SendMailAsync不是TAP。你无法等待它。其次,发送电子邮件时不需要存在线程,大多数"等待"时间是服务器响应的延迟。最后,"是一次发送大量电子邮件的更好方式"?你发现了什么问题?

了解是否存在性能问题的最佳方法是尝试。

答案 1 :(得分:0)

SendMailAsync并且所有使用任务并行库的方法都在线程池线程中执行,但是如果需要,可以使它们使用新线程。这意味着,不是创建新线程,而是从池中挑选可用线程,并在方法完成时返回。

池中的线程数因.NET和OS的版本,内核数量等而异。它可以从.NET 4中的每个核心25个线程到.NET 4.5中的数百个或每个核心。服务器操作系统。

IO绑定(磁盘,网络)任务的另一个优化是,不使用线程,而是使用IO完成端口。粗略地说,这是IO操作(磁盘或网络)完成时IO堆栈的回调。这样,框架不会浪费等待IO调用完成的线程。

当您启动异步网络操作时,.NET进行网络调用,注册回调并释放线程池线程。当调用结束时,框架会得到通知,并在线程池线程上调度其余的异步方法(基本上是awaitContinueWith之后的内容)。

提交100个异步操作并不意味着将使用100个线程,也不意味着所有100个线程将并行执行。相反,该框架将考虑核心的数量,负载和可执行的可用线程的数量尽可能多,而不会损害整体性能。等待网络调用甚至可能根本不使用线程,而处理消息本身将在线程池线程上执行

答案 2 :(得分:0)

SendMailAsync只是围绕SendAsync方法的TPL包装器,但两种方法都不使用线程。相反,它使用称为IO completion port (IOCP)的模型。

当您调用SendMailAsync时,您的线程会将邮件消息写入连接到SMTP服务器的套接字,并向操作系统注册回调,当客户端从服务器收到响应时,该回调将被执行。此回调由"完成"触发。事件由IO完成端口处理。

在由线程池管理的许多IO完成线程之一上调用回调本身。这个线程池只处理来自IO完成事件的回调。完成回调的部分标记为Task调用返回的SendMailAsync为"已完成",允许任何等待代码在其自己的上下文中开始执行。