我举个线程间不安全的例子,或许对线程间安全理解更深刻一些
{
System.Threading.Thread thread1 = new System.Threading.Thread(new System.Threading.ThreadStart(threadfun1));
thread1.Start();
}
void threadfun1()
{
double dNumber=0;
if (double.TryParse(txtNumber.Text, out dNumber) == true)
{
double dReciprocal = 1 / Convert.ToDouble(Convert.ToDouble(txtNumber.Text));
txtNumber.Text = dReciprocal.ToString();
}
}
如果是多个线程的话,执行if (double.TryParse(txtNumber.Text, out dNumber) == true)还没有问题
但是执行double dReciprocal = 1 / Convert.ToDouble(Convert.ToDouble(txtNumber.Text));可能就出问题了,
因为这段时间txtNumber.Text值可能己经被其它线程改成0了,0没有倒数数,就会出错。(当然使用dNumber也不会出错)
使用代理后
private void button1_Click(object sender, EventArgs e)
{
System.Threading.Thread thread1 = new System.Threading.Thread(new System.Threading.ThreadStart(threadfun1));
thread1.Start();
}
void threadfun1()
{
funReciprocal(txtNumber.Text);
}
delegate void dltReciprocal(string strNumber);
void funReciprocal(string strNumber)
{
if (txtNumber.InvokeRequired)
{
//由线程调用时txtNumber.InvokeRequired为真,进入这里
dltReciprocal evtReciprocal = new dltReciprocal(funReciprocal);txtNumber.Invoke(evtReciprocal, new object[] { strNumber });//Invoke的作用是执行权交到txtNumber的所有者来执行(在所有者线程中排队执行)。因为代理函数在所有者线程中排队执行,因此不会出现函数没有执行完,UI变量被更新的情况。
}
else
{
//由所有者(窗体)调用时txtNumber.InvokeRequired为假,进入这里
if (double.TryParse(txtNumber.Text, out dNumber) == true)
{
double dReciprocal = 1 / Convert.ToDouble(txtNumber.Text);
txtNumber.Text = dReciprocal.ToString();
}
}
}