C# 创建新线程时运行false if语句
我正在编写一个程序,它将通过电子邮件向邮件列表中的任何人发送Cat事实(不是垃圾邮件,这更像是一种学习体验)。我有两个数组,一个用于事实(没有问题),一个用于电子邮件。用于电子邮件的语句总是会抛出异常(即使在try/catch块中也是如此),并且在运行该语句时,我的所有if语句都会被完全忽略C# 创建新线程时运行false if语句,c#,multithreading,C#,Multithreading,我正在编写一个程序,它将通过电子邮件向邮件列表中的任何人发送Cat事实(不是垃圾邮件,这更像是一种学习体验)。我有两个数组,一个用于事实(没有问题),一个用于电子邮件。用于电子邮件的语句总是会抛出异常(即使在try/catch块中也是如此),并且在运行该语句时,我的所有if语句都会被完全忽略 public void Broadcast() { fact++; if (fact ==factCount) { fact = 0; } String[]
public void Broadcast() {
fact++;
if (fact ==factCount) {
fact = 0;
}
String[] mailArray = mailingList.ToArray();
String[] factArray = factList.ToArray();
int i = mailArray.Length-1;
String sendFact = factArray[fact];
while (i>=0) {
String s = mailArray[i];
var t = new Thread(() => Mail(mailArray[i], sendFact));
t.IsBackground = true;
t.Start();
i--;
if (i==-1) {
break;
}
}
问题在于:
var t = new Thread(() => Mail(mailArray[i], sendFact));
即使“i”为-1,while语句仍会运行,中断也会被忽略。最初我反向运行“I”,从0开始,然后计数到mailArray.Length-1。它仍然给出了相同的问题,忽略了while和break,当我将它们设置为反向运行时
这是创建新线程的问题吗
编辑:
我动议:
var t = new Thread(() => Mail(mailArray[i], sendFact));
t.IsBackground = true;
t.Start();
创建一个新方法,并调用它,而不是上面的代码-这工作得非常好。您正在创建一个循环变量上的闭包-这是一个 直接使用
s
,因为您已经为其指定了当前值,可以修复它:
while (i>=0)
{
string s = mailArray[i];
var t = new Thread(() => Mail(s, sendFact));
//..
}
这是创建新线程的问题吗
有点。在lambda表达式中捕获i
,然后对其进行更改是一个问题。这意味着当线程执行lambda表达式时,它在创建线程的循环迭代中采用当前值i
,而不是i
最简单的解决方案是在循环内声明一个新的局部变量,将i
复制到其中,然后在lambda表达式中使用该变量:
while (i >= 0)
{
var copy = i;
String s = mailArray[i];
var t = new Thread(() => Mail(mailArray[copy], sendFact));
t.IsBackground = true;
t.Start();
i--;
}
while (i >= 0)
{
String s = mailArray[i];
var t = new Thread(() => Mail(s, sendFact));
t.IsBackground = true;
t.Start();
i--;
}
() => Mail(mailArray[i], sendFact)
int temp = i;
var t = new Thread(() => Mail(mailArray(temp), sendFact));
或者只需使用已在lambda表达式外部初始化的s
:
while (i >= 0)
{
var copy = i;
String s = mailArray[i];
var t = new Thread(() => Mail(mailArray[copy], sendFact));
t.IsBackground = true;
t.Start();
i--;
}
while (i >= 0)
{
String s = mailArray[i];
var t = new Thread(() => Mail(s, sendFact));
t.IsBackground = true;
t.Start();
i--;
}
() => Mail(mailArray[i], sendFact)
int temp = i;
var t = new Thread(() => Mail(mailArray(temp), sendFact));
或者,更容易理解的是,IMO,只需使用foreach
循环:
foreach (var item in mailArray)
{
Thread t = new Thread(() => Mail(item, sendFact)) { IsBackground = true };
t.Start();
}
在C#3和C#4下也会出现同样的问题,但在C#5下,在foreach
循环中捕获迭代器变量的行为是固定的
(您应该考虑使用<代码>任务>代码>而不是<代码>线程< /代码>,并且可能使用“<代码>并行”之类的东西.Furace >,BTW.
这是一个常见的问题,它与这个lambda表达式的创建有关:
while (i >= 0)
{
var copy = i;
String s = mailArray[i];
var t = new Thread(() => Mail(mailArray[copy], sendFact));
t.IsBackground = true;
t.Start();
i--;
}
while (i >= 0)
{
String s = mailArray[i];
var t = new Thread(() => Mail(s, sendFact));
t.IsBackground = true;
t.Start();
i--;
}
() => Mail(mailArray[i], sendFact)
int temp = i;
var t = new Thread(() => Mail(mailArray(temp), sendFact));
基本上,您告诉thread类启动一个新线程,当它启动时,执行该代码
不幸的是,它不会对当时i
的值进行快照,因此假设由于时间原因,在线程实际启动之前,您设法增加了i
。线程将使用当前值i
,而不是创建lambda时的值i
调用该lambda
然而,这很容易解决
在while循环中,添加一个临时变量以捕获i
的当前值,并在lambda表达式中使用该变量:
while (i >= 0)
{
var copy = i;
String s = mailArray[i];
var t = new Thread(() => Mail(mailArray[copy], sendFact));
t.IsBackground = true;
t.Start();
i--;
}
while (i >= 0)
{
String s = mailArray[i];
var t = new Thread(() => Mail(s, sendFact));
t.IsBackground = true;
t.Start();
i--;
}
() => Mail(mailArray[i], sendFact)
int temp = i;
var t = new Thread(() => Mail(mailArray(temp), sendFact));
有关更多信息,请查看以下链接:。您会遇到什么异常?lambda捕获的是
i
变量,而不是值。因此,当线程开始时,i
是-1
。相关:一般建议:使用foreach循环,不要作为初学者使用线程(很难正确)。是的,这很有效。我试着让字符串s看看它是否会抛出异常,我没有想到只用s来启动线程。