新手经常会遇到这样的问题: a线程去访问b线程的控件,编译器报错(.net1.0编译时好像不会报,.net2.0是肯定会的).
解决方法有3种:
1, 不安全的方法: 将 Control.CheckForIllegalCrossThreadCalls 设置为false (.net1.0中没有)
2,安全的方法: 异步委托
3, 安全的方法: 就是使用BackgroundWorker来替代你自己创建的线程(.net1.0中没有)
以下是示例代码
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
usingSystem;
usingSystem.ComponentModel;
usingSystem.Threading;
usingSystem.Windows.Forms;

namespaceCrossThreadDemo


{
publicclassForm1:Form


{
//Thisdelegateenablesasynchronouscallsforsetting
//thetextpropertyonaTextBoxcontrol.
delegatevoidSetTextCallback(stringtext);

//Thisthreadisusedtodemonstrateboththread-safeand
//unsafewaystocallaWindowsFormscontrol.
privateThreaddemoThread=null;

//ThisBackgroundWorkerisusedtodemonstratethe
//preferredwayofperformingasynchronousoperations.
privateBackgroundWorkerbackgroundWorker1;

privateTextBoxtextBox1;
privateButtonsetTextUnsafeBtn;
privateButtonsetTextSafeBtn;
privateButtonsetTextBackgroundWorkerBtn;

privateSystem.ComponentModel.IContainercomponents=null;

publicForm1()


{
InitializeComponent();
}

protectedoverridevoidDispose(booldisposing)


{
if(disposing&&(components!=null))


{
components.Dispose();
}
base.Dispose(disposing);
}

//Thiseventhandlercreatesathreadthatcallsa
//WindowsFormscontrolinanunsafeway.
privatevoidsetTextUnsafeBtn_Click(
objectsender,
EventArgse)


{
this.demoThread=
newThread(newThreadStart(this.ThreadProcUnsafe));

this.demoThread.Start();
}

//Thismethodisexecutedontheworkerthreadandmakes
//anunsafecallontheTextBoxcontrol.
privatevoidThreadProcUnsafe()


{
this.textBox1.Text="Thistextwassetunsafely.";
}

//Thiseventhandlercreatesathreadthatcallsa
//WindowsFormscontrolinathread-safeway.
privatevoidsetTextSafeBtn_Click(
objectsender,
EventArgse)


{
this.demoThread=
newThread(newThreadStart(this.ThreadProcSafe));

this.demoThread.Start();
}

//Thismethodisexecutedontheworkerthreadandmakes
//athread-safecallontheTextBoxcontrol.
privatevoidThreadProcSafe()


{
this.SetText("Thistextwassetsafely.");
}

//Thismethoddemonstratesapatternformakingthread-safe
//callsonaWindowsFormscontrol.
//
//Ifthecallingthreadisdifferentfromthethreadthat
//createdtheTextBoxcontrol,thismethodcreatesa
//SetTextCallbackandcallsitselfasynchronouslyusingthe
//Invokemethod.
//
//Ifthecallingthreadisthesameasthethreadthatcreated
//theTextBoxcontrol,theTextpropertyissetdirectly.

privatevoidSetText(stringtext)


{
//InvokeRequiredrequiredcomparesthethreadIDofthe
//callingthreadtothethreadIDofthecreatingthread.
//Ifthesethreadsaredifferent,itreturnstrue.
if(this.textBox1.InvokeRequired)


{
SetTextCallbackd=newSetTextCallback(SetText);

this.Invoke(d,newobject[]
{text});
}
else


{
this.textBox1.Text=text;
}
}

//Thiseventhandlerstartstheform's
//BackgroundWorkerbycallingRunWorkerAsync.
//
//TheTextpropertyoftheTextBoxcontrolisset
//whentheBackgroundWorkerraisestheRunWorkerCompleted
//event.
privatevoidsetTextBackgroundWorkerBtn_Click(
objectsender,
EventArgse)


{
this.backgroundWorker1.RunWorkerAsync();
}

//ThiseventhandlersetstheTextpropertyoftheTextBox
//control.Itiscalledonthethreadthatcreatedthe
//TextBoxcontrol,sothecallisthread-safe.
//
//BackgroundWorkeristhepreferredwaytoperformasynchronous
//operations.

privatevoidbackgroundWorker1_RunWorkerCompleted(
objectsender,
RunWorkerCompletedEventArgse)


{
this.textBox1.Text=
"ThistextwassetsafelybyBackgroundWorker.";
}


WindowsFormDesignergeneratedcode#regionWindowsFormDesignergeneratedcode

privatevoidInitializeComponent()


{
this.textBox1=newSystem.Windows.Forms.TextBox();
this.setTextUnsafeBtn=newSystem.Windows.Forms.Button();
this.setTextSafeBtn=newSystem.Windows.Forms.Button();
this.setTextBackgroundWorkerBtn=newSystem.Windows.Forms.Button();
this.backgroundWorker1=newSystem.ComponentModel.BackgroundWorker();
this.SuspendLayout();
//
//textBox1
//
this.textBox1.Location=newSystem.Drawing.Point(12,12);
this.textBox1.Name="textBox1";
this.textBox1.Size=newSystem.Drawing.Size(240,20);
this.textBox1.TabIndex=0;
//
//setTextUnsafeBtn
//
this.setTextUnsafeBtn.Location=newSystem.Drawing.Point(15,55);
this.setTextUnsafeBtn.Name="setTextUnsafeBtn";
this.setTextUnsafeBtn.TabIndex=1;
this.setTextUnsafeBtn.Text="UnsafeCall";
this.setTextUnsafeBtn.Click+=newSystem.EventHandler(this.setTextUnsafeBtn_Click);
//
//setTextSafeBtn
//
this.setTextSafeBtn.Location=newSystem.Drawing.Point(96,55);
this.setTextSafeBtn.Name="setTextSafeBtn";
this.setTextSafeBtn.TabIndex=2;
this.setTextSafeBtn.Text="SafeCall";
this.setTextSafeBtn.Click+=newSystem.EventHandler(this.setTextSafeBtn_Click);
//
//setTextBackgroundWorkerBtn
//
this.setTextBackgroundWorkerBtn.Location=newSystem.Drawing.Point(177,55);
this.setTextBackgroundWorkerBtn.Name="setTextBackgroundWorkerBtn";
this.setTextBackgroundWorkerBtn.TabIndex=3;
this.setTextBackgroundWorkerBtn.Text="SafeBWCall";
this.setTextBackgroundWorkerBtn.Click+=newSystem.EventHandler(this.setTextBackgroundWorkerBtn_Click);
//
//backgroundWorker1
//
this.backgroundWorker1.RunWorkerCompleted+=newSystem.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
//
//Form1
//
this.ClientSize=newSystem.Drawing.Size(268,96);
this.Controls.Add(this.setTextBackgroundWorkerBtn);
this.Controls.Add(this.setTextSafeBtn);
this.Controls.Add(this.setTextUnsafeBtn);
this.Controls.Add(this.textBox1);
this.Name="Form1";
this.Text="Form1";
this.ResumeLayout(false);
this.PerformLayout();

}

#endregion


[STAThread]
staticvoidMain()


{
Application.EnableVisualStyles();
Application.Run(newForm1());
}

}
}
在使用方法2时的注意事项: 不要将除了控件访问外其他逻辑代码放到委托的回调方法中.
解决方法有3种:
1, 不安全的方法: 将 Control.CheckForIllegalCrossThreadCalls 设置为false (.net1.0中没有)
2,安全的方法: 异步委托
3, 安全的方法: 就是使用BackgroundWorker来替代你自己创建的线程(.net1.0中没有)
以下是示例代码


<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->


















































































































































































































































在使用方法2时的注意事项: 不要将除了控件访问外其他逻辑代码放到委托的回调方法中.