Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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# 使用LINQ获取1000_C#_Linq_Parallel Processing_Enumerable - Fatal编程技术网

C# 使用LINQ获取1000

C# 使用LINQ获取1000,c#,linq,parallel-processing,enumerable,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 =

好的,我的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);
string[]files=System.IO.Directory.GetFiles(@“C:\Mail\”,“*.csv”);
Parallel.ForEach(文件,当前文件=>
{
字符串文件名=当前文件;
StreamReader=新的StreamReader(文件名);
var emailList=新列表();
while(reader.Peek()>=0)
{
emailList.Add(reader.ReadLine());
}
\\这是我需要做linq的地方?
IEnumerable list=电子邮件列表
var message=new System.Net.Mail.MailMessage();
foreach(列表中的var s)
{
MailAddress MailAddress=新的邮件地址;
message.Bcc.Add(邮件地址);
}
message.Subject=txtSubject.Text;
message.From=新系统.Net.Mail.MailAddress(txtFrom.Text);
message.Body=txtMessage.Text;
message.IsBodyHtml=true;
var smtp=new System.Net.Mail.SmtpClient();
smtp.Send(message);

您似乎在寻找一种
批处理方法。下面是一个实现:

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;
    }
}

另一方面,您可以使用
file.ReadLines
来获取表示文件中行的
IEnumerable
,而不是使用
StreamReader
来读取文件行。它甚至还有一个附带的好处,即流式传输数据,而不是先将所有行拉入内存。

将电子邮件发送代码移动到一个单独的方法,在初始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);
var emailList=newlist();
while(reader.Peek()>=0)
{
emailList.Add(reader.ReadLine());
如果(emailList.Count==1000)
{
发送电子邮件(电子邮件列表);
emailList=新列表();
}
}
//如果有的话,把剩下的寄出去
如果(emailList.Any())发送电子邮件(emailList);

无论如何,这在我看来要干净得多,因为您的电子邮件发送方法与您获取电子邮件地址的方式在逻辑上是分开的。

如果您想使用linq,我相信这将完全满足您的要求,在下面修改,在组中发送=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();
}
公共静态IEnumerable拆分(此IEnumerable源,int组)
{
返回源
.Select((x,i)=>new{Index=i,Value=x})
.GroupBy(x=>x.索引/组)
.Select(x=>x.Select(v=>v.Value).ToList())
.ToList();
}

这应该是评论而不是回答。请让我知道,如果是这样的话,我会删除和更改

那么问题出在哪里?你根本不需要Linq-将你的电子邮件发送代码移动到一个单独的方法中,在你的初始地址足够后再调用它loop@BrokenGlass你永远不需要林克,它可能r可能不是解决此问题的可接受工具。这样,您将在所有电子邮件地址上迭代两次。BrokenGlass的实现只迭代一次。虽然从技术上讲,这解决了如何在Linq中实现这一点。@RGraham在最后查看编辑;这是OP使用不希望的机制将文件读入的结果内存,这很容易解决。不是
ReadLines
在内部使用StreamReader吗?我不认为StreamReader会将所有内容都放在内存中,是吗?你能提供一个源代码吗?因为我已经在很多情况下使用过它,我真的不应该使用它!!@RGraham
ReadLines
流式处理数据是的;它会在枚举时获取下一行数据erator要求它,而不是全部提前。OP的代码,尽管使用了
StreamReader
,但并不流式传输数据;相反,它使用stream reader将所有数据拉入一个列表,从而阻止流式传输数据。
reader.Peek()
是一个真正的性能杀手,
string line;while((line=reader.ReadLine())!=null){emailList.Add(line);
是一种更好的方法。@ScottChamberlain更好的方法是只使用
foreach(File.ReadLines(filename)中的var行)
请解释-1,谢谢。我可以根据对-1的评论更新我的答案。
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();
}