Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 你如何利用任务衍生出大量的“任务”;火与遗忘”;工作_C#_.net_Task Parallel Library - Fatal编程技术网

C# 你如何利用任务衍生出大量的“任务”;火与遗忘”;工作

C# 你如何利用任务衍生出大量的“任务”;火与遗忘”;工作,c#,.net,task-parallel-library,C#,.net,Task Parallel Library,我有一个Windows应用程序,我想向它介绍一些功能。这个场景是,我有一个类,它有一个Process方法,该方法将MailMessages的集合传递给它,以及当前的IMAP连接(使用AE.Net.Mail) 我想在另一个类中尽可能多地派生线程到Execute方法,该类接受单个MailMessage项,并将MailMessage发送到数据库,然后使用IMAP连接从服务器上删除MailMessage 我不太担心跟踪这些过程——我正在处理大量的电子邮件,也不担心我在向DB写信或删除邮件时会遇到一些错误

我有一个Windows应用程序,我想向它介绍一些功能。这个场景是,我有一个类,它有一个
Process
方法,该方法将
MailMessage
s的集合传递给它,以及当前的IMAP连接(使用AE.Net.Mail)

我想在另一个类中尽可能多地派生线程到
Execute
方法,该类接受单个
MailMessage
项,并将
MailMessage
发送到数据库,然后使用IMAP连接从服务器上删除
MailMessage

我不太担心跟踪这些过程——我正在处理大量的电子邮件,也不担心我在向DB写信或删除邮件时会遇到一些错误。我只需要应用程序尽快通过大量邮件

我一直在玩弄
Task.Factory.StartNew
,但我真的不知道自己在做什么。我似乎无法启动它…以下是我尝试过的:

Task test = Task.Factory.StartNew(() =>
{
  foreach (var mailMessage in _mms)
  {
    new ProcessMessage().Execute(mailMessage, imapConn);
  }

});

我很确定在lamda表达式中不应该有循环,当我运行它时,它似乎没有进入
ProcessMessage.Execute

在lamdba表达式中绝对不应该有循环。试试这个:

_mms.ForEach(mms => {
    Task.Factory.StartNew(() => ProcessMessage().Execute(mailMessage, imapConn))
});
如果您不担心跟踪结果或任何事情,则不需要保存任务的实例,例如Task test=。。。。您只需使用
Task.Factory.StartNew()
在新线程中启动方法执行,这样我们就可以为您要处理的每封邮件启动一个新任务,并让线程池为我们处理事情


另外,
Task.Factory.StartNew
将用于在另一个返回邮件消息的线程中设置方法调用,因此,如果调用的是void方法,则无需执行此操作。
Task
语法总是指使用新任务启动的方法的返回类型。

它应该在单独的线程中执行每次执行(这样您就知道现在在做什么:)


现在,您正在将foreach循环作为一个单独的任务来执行,但您可能希望将每个迭代作为一个单独的任务来执行。您应该尝试Parallel.ForEach:

        Parallel.ForEach(_mms, mailMessage =>
            {
                new ProcessMessage().Execute(mailMessage, imapConn);
            });
这将并行执行迭代,这似乎是您正在尝试执行的操作。

另一个选项是在集合上使用:

_mms.AsParallel()
    .ForAll(mm => ProcessMessage().Execute(mm, imapConn));
当我运行它时,它似乎没有进入
ProcessMessage.Execute

那么你的代码肯定还有其他问题,你的代码肯定能工作。如果您不想(或不能)并行化代码,在lambda中有一个循环可能是完全合适的


如果您确实想将其并行化(这在您的问题中不是很清楚),您可以使用例如
Parallel.ForEach()
,它正是为此而优化的。

当您可以使用
Task
s时,为什么建议使用
ThreadPool
Thread
?创建大量的
线程是个坏主意。@svick你和像你这样的人能不能停止说这是个坏主意,并说出为什么这是个坏主意?如果有线程,为什么建议使用任务?你真的认为创建1000个任务比创建1000个排队线程好吗?当然,1000个
Task
s比1000个
Thread
s好得多(它们没有排队)。每个
线程
消耗1 MB内存(和一些其他资源),而1000个
任务
s将使用
线程池
以更小的内存占用执行。因此,如果您在32位进程中运行,您的方法将极大地浪费资源,并且还很容易导致
OutOfMemoryException
。使用
ThreadPool
和创建新的
线程之间存在巨大差异。我想说的是,您的第二个代码片段是对资源的严重浪费,因为它没有使用
ThreadPool
。您的第一个代码片段要好得多,但是使用
Task
s会更好,因为它有更好的API,并且还有一些性能改进。如果您直接使用
ThreadPool
调用“创建排队线程”,那么我想您可能不知道线程是什么,因为这样说会产生很大的误导。但我承认我不知道“tcb”是什么意思,你能告诉我这一点吗?你的回答有些不准确
Parallel.ForEach()
不会将每个迭代作为单独的
任务执行,因为使用一个
任务执行更多迭代的开销更小。如果“并行执行所有迭代”的意思是“一次执行所有迭代”,那么这也是错误的。@svick我不记得有人声称并行。Foreach()在单独的任务中执行每个迭代。。。更准确地说,我可能应该删除“all”一词。你写答案的方式意味着:“你可能希望将每个迭代作为一个单独的任务来执行。你应该尝试Parallel.ForEach[为此]”,它不会并行执行/all/iterations,它将按硬件和tpl库确定的批量执行它们。@JasonHiggins他提出了一种更易于阅读和更高效的方法(通过使用
Parallel.ForEach()
)。他使用了一种方法(
ForEach()
,而不是
ForEach
),这种方法有时会遭到反对。所以,我不会说他是下一个Jon Skeet:-)OP有关于TPL的具体问题,这就是为什么我决定在回答中使用这种方法。此外,关于foreach vs foreach,我的理解是,在存在潜在不必要副作用的情况下,foreach扩展方法是不受欢迎的,我不认为使用TPL执行无效方法是使用此版本的坏情况。如果你对foreach更满意
        Parallel.ForEach(_mms, mailMessage =>
            {
                new ProcessMessage().Execute(mailMessage, imapConn);
            });
_mms.AsParallel()
    .ForAll(mm => ProcessMessage().Execute(mm, imapConn));