如何对 Windows 窗体控件进行线程安全调用.docx

上传人:b****5 文档编号:29970097 上传时间:2023-08-03 格式:DOCX 页数:22 大小:26.13KB
下载 相关 举报
如何对 Windows 窗体控件进行线程安全调用.docx_第1页
第1页 / 共22页
如何对 Windows 窗体控件进行线程安全调用.docx_第2页
第2页 / 共22页
如何对 Windows 窗体控件进行线程安全调用.docx_第3页
第3页 / 共22页
如何对 Windows 窗体控件进行线程安全调用.docx_第4页
第4页 / 共22页
如何对 Windows 窗体控件进行线程安全调用.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

如何对 Windows 窗体控件进行线程安全调用.docx

《如何对 Windows 窗体控件进行线程安全调用.docx》由会员分享,可在线阅读,更多相关《如何对 Windows 窗体控件进行线程安全调用.docx(22页珍藏版)》请在冰豆网上搜索。

如何对 Windows 窗体控件进行线程安全调用.docx

如何对Windows窗体控件进行线程安全调用

使用多线程提高Windows窗体应用程序的性能时,必须注意以线程安全方式调用控件。

示例

访问Windows窗体控件本质上不是线程安全的。

如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。

还可能出现其他与线程相关的bug,包括争用情况和死锁。

确保以线程安全方式访问控件非常重要。

.NETFramework有助于在以非线程安全方式访问控件时检测到这一问题。

在调试器中运行应用程序时,如果创建某控件的线程之外的其他线程试图调用该控件,则调试器会引发一个InvalidOperationException,并显示以下消息:

“从不是创建控件控件名称的线程访问它。

此异常在调试期间和运行时的某些情况下可靠地发生。

强烈建议您在显示此错误信息时修复此问题。

在调试以.NETFramework2.0版之前的.NETFramework编写的应用程序时,可能会出现此异常。

注意:

可以通过将CheckForIllegalCrossThreadCalls属性的值设置为false来禁用此异常。

这会使控件以与在VisualStudio2003下相同的方式运行。

下面的代码示例演示如何从辅助线程以线程安全方式和非线程安全方式调用Windows窗体控件。

它演示一种以非线程安全方式设置TextBox控件的Text属性的方法,还演示两种以线程安全方式设置Text属性的方法。

VisualBasic 

复制代码

ImportsSystem

ImportsSystem.ComponentModel

ImportsSystem.Threading

ImportsSystem.Windows.Forms

PublicClassForm1

InheritsForm

'Thisdelegateenablesasynchronouscallsforsetting

'thetextpropertyonaTextBoxcontrol.

DelegateSubSetTextCallback([text]AsString)

'Thisthreadisusedtodemonstrateboththread-safeand

'unsafewaystocallaWindowsFormscontrol.

PrivatedemoThreadAsThread=Nothing

'ThisBackgroundWorkerisusedtodemonstratethe

'preferredwayofperformingasynchronousoperations.

PrivateWithEventsbackgroundWorker1AsBackgroundWorker

PrivatetextBox1AsTextBox

PrivateWithEventssetTextUnsafeBtnAsButton

PrivateWithEventssetTextSafeBtnAsButton

PrivateWithEventssetTextBackgroundWorkerBtnAsButton

PrivatecomponentsAsSystem.ComponentModel.IContainer=Nothing

 

PublicSubNew()

InitializeComponent()

EndSub

 

ProtectedOverridesSubDispose(disposingAsBoolean)

IfdisposingAndAlso(componentsIsNotNothing)Then

components.Dispose()

EndIf

MyBase.Dispose(disposing)

EndSub

 

'Thiseventhandlercreatesathreadthatcallsa

'WindowsFormscontrolinanunsafeway.

PrivateSubsetTextUnsafeBtn_Click(_

ByValsenderAsObject,_

ByValeAsEventArgs)HandlessetTextUnsafeBtn.Click

Me.demoThread=NewThread(_

NewThreadStart(AddressOfMe.ThreadProcUnsafe))

Me.demoThread.Start()

EndSub

 

'Thismethodisexecutedontheworkerthreadandmakes

'anunsafecallontheTextBoxcontrol.

PrivateSubThreadProcUnsafe()

Me.textBox1.Text="Thistextwassetunsafely."

EndSub

'Thiseventhandlercreatesathreadthatcallsa

'WindowsFormscontrolinathread-safeway.

PrivateSubsetTextSafeBtn_Click(_

ByValsenderAsObject,_

ByValeAsEventArgs)HandlessetTextSafeBtn.Click

Me.demoThread=NewThread(_

NewThreadStart(AddressOfMe.ThreadProcSafe))

Me.demoThread.Start()

EndSub

 

'Thismethodisexecutedontheworkerthreadandmakes

'athread-safecallontheTextBoxcontrol.

PrivateSubThreadProcSafe()

Me.SetText("Thistextwassetsafely.")

EndSub

'Thismethoddemonstratesapatternformakingthread-safe

'callsonaWindowsFormscontrol.

'

'Ifthecallingthreadisdifferentfromthethreadthat

'createdtheTextBoxcontrol,thismethodcreatesa

'SetTextCallbackandcallsitselfasynchronouslyusingthe

'Invokemethod.

'

'Ifthecallingthreadisthesameasthethreadthatcreated

'theTextBoxcontrol,theTextpropertyissetdirectly.

PrivateSubSetText(ByVal[text]AsString)

'InvokeRequiredrequiredcomparesthethreadIDofthe

'callingthreadtothethreadIDofthecreatingthread.

'Ifthesethreadsaredifferent,itreturnstrue.

IfMe.textBox1.InvokeRequiredThen

DimdAsNewSetTextCallback(AddressOfSetText)

Me.Invoke(d,NewObject(){[text]})

Else

Me.textBox1.Text=[text]

EndIf

EndSub

'Thiseventhandlerstartstheform's

'BackgroundWorkerbycallingRunWorkerAsync.

'

'TheTextpropertyoftheTextBoxcontrolisset

'whentheBackgroundWorkerraisestheRunWorkerCompleted

'event.

PrivateSubsetTextBackgroundWorkerBtn_Click(_

ByValsenderAsObject,_

ByValeAsEventArgs)HandlessetTextBackgroundWorkerBtn.Click

Me.backgroundWorker1.RunWorkerAsync()

EndSub

 

'ThiseventhandlersetstheTextpropertyoftheTextBox

'control.Itiscalledonthethreadthatcreatedthe

'TextBoxcontrol,sothecallisthread-safe.

'

'BackgroundWorkeristhepreferredwaytoperformasynchronous

'operations.

PrivateSubbackgroundWorker1_RunWorkerCompleted(_

ByValsenderAsObject,_

ByValeAsRunWorkerCompletedEventArgs)_

HandlesbackgroundWorker1.RunWorkerCompleted

Me.textBox1.Text=_

"ThistextwassetsafelybyBackgroundWorker."

EndSub

#Region"WindowsFormDesignergeneratedcode"

 

PrivateSubInitializeComponent()

Me.textBox1=NewSystem.Windows.Forms.TextBox()

Me.setTextUnsafeBtn=NewSystem.Windows.Forms.Button()

Me.setTextSafeBtn=NewSystem.Windows.Forms.Button()

Me.setTextBackgroundWorkerBtn=NewSystem.Windows.Forms.Button()

Me.backgroundWorker1=NewSystem.ComponentModel.BackgroundWorker()

Me.SuspendLayout()

'

'textBox1

'

Me.textBox1.Location=NewSystem.Drawing.Point(12,12)

Me.textBox1.Name="textBox1"

Me.textBox1.Size=NewSystem.Drawing.Size(240,20)

Me.textBox1.TabIndex=0

'

'setTextUnsafeBtn

'

Me.setTextUnsafeBtn.Location=NewSystem.Drawing.Point(15,55)

Me.setTextUnsafeBtn.Name="setTextUnsafeBtn"

Me.setTextUnsafeBtn.TabIndex=1

Me.setTextUnsafeBtn.Text="UnsafeCall"

'

'setTextSafeBtn

'

Me.setTextSafeBtn.Location=NewSystem.Drawing.Point(96,55)

Me.setTextSafeBtn.Name="setTextSafeBtn"

Me.setTextSafeBtn.TabIndex=2

Me.setTextSafeBtn.Text="SafeCall"

'

'setTextBackgroundWorkerBtn

'

Me.setTextBackgroundWorkerBtn.Location=NewSystem.Drawing.Point(177,55)

Me.setTextBackgroundWorkerBtn.Name="setTextBackgroundWorkerBtn"

Me.setTextBackgroundWorkerBtn.TabIndex=3

Me.setTextBackgroundWorkerBtn.Text="SafeBWCall"

'

'backgroundWorker1

'

'

'Form1

'

Me.ClientSize=NewSystem.Drawing.Size(268,96)

Me.Controls.Add(setTextBackgroundWorkerBtn)

Me.Controls.Add(setTextSafeBtn)

Me.Controls.Add(setTextUnsafeBtn)

Me.Controls.Add(textBox1)

Me.Name="Form1"

Me.Text="Form1"

Me.ResumeLayout(False)

Me.PerformLayout()

EndSub'InitializeComponent

#EndRegion

_

SharedSubMain()

Application.EnableVisualStyles()

Application.Run(NewForm1())

EndSub

EndClass

C# 

复制代码

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.

//

//BackgroundWorkeristhepreferredwaytoperformasy

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > IT计算机 > 互联网

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1