使用LINQ获取1000

时间:2013-10-14 14:26:58

标签: c# linq parallel-processing enumerable

好的,我的linq技能不是很好所以我试着做以下几点。

说我有6000条记录(电子邮件地址) 我想添加前1000个添加到密送,发送, 拿下一个1000添加到密送,发送, 取1000加入密送,发送等......

我开始打字了,

string[] files = System.IO.Directory.GetFiles(@"C:\Mail\ ", "*.csv");

Parallel.ForEach(files, currentFile =>
{
    string filename = currentFile;
    StreamReader reader = new StreamReader(filename);
    var emailList = new List<String>();
    while (reader.Peek() >= 0)
    {
        emailList.Add(reader.ReadLine());
    }
    \\Here is where I need to do the linq?
    IEnumerable<string> list = emailList

    var message = new System.Net.Mail.MailMessage();
    foreach (var s in list)
    {
        MailAddress mailAddress = new MailAddress(s);
        message.Bcc.Add(mailAddress);
    }

    message.Subject = txtSubject.Text;
    message.From = new System.Net.Mail.MailAddress(txtFrom.Text);
    message.Body = txtMessage.Text;
    message.IsBodyHtml = true;
    var smtp = new System.Net.Mail.SmtpClient();

    smtp.Send(message);

3 个答案:

答案 0 :(得分:6)

您似乎在寻找Batch方法。这是一个实现:

public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int batchSize)
{
    List<T> buffer = new List<T>(batchSize);

    foreach (T item in source)
    {
        buffer.Add(item);

        if (buffer.Count >= batchSize)
        {
            yield return buffer;
            buffer = new List<T>(batchSize);
        }
    }
    if (buffer.Count > 0)
    {
        yield return buffer;
    }
}

您现在可以写:

foreach(var batch in emailList.Batch(1000))
{
    var message = CreateMessage();
    foreach(var email in batch)
    {
        message.Bcc.Add(email);
    }
    message.Send();
}

另一方面,您可以使用StreamReader来获取代表文件中行的File.ReadLines,而不是使用IEnumerable<string>来读取文件的行。它甚至具有流式传输数据的附带好处,而不是首先将所有线路拉入内存。

答案 1 :(得分:1)

将您的电子邮件发送代码移到一个单独的方法中,并在您的初始while循环中有足够的地址后调用它:

var emailList = new List<String>();
while (reader.Peek() >= 0)
{
    emailList.Add(reader.ReadLine());
    if(emailList.Count == 1000)
    {
        SendEmails(emailList);
        emailList = new List<String>();
    }
}
//send the rest, if any
if(emailList.Any()) SendEmails(emailList);

无论如何,这更加清晰,因为您的电子邮件发送方式在逻辑上与您获取电子邮件地址的方式分开。

答案 2 :(得分:-1)

如果你想用linq做这件事,我相信这个answer会完全按照你要求的方式进行修改,在你发送给group = 1000的地方进行修改

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int group)
{
    return  source
        .Select((x, i) => new { Index = i, Value = x })
        .GroupBy(x => x.Index / group)
        .Select(x => x.Select(v => v.Value).ToList())
        .ToList();
}

这应该是评论,而不是答案。请告诉我,如果是这样的话,我会删除并更改