当前位置: 首页 > 编程语言 > C#

C#学习教程:.NETBackGroundWorker–InvalidOperationException-InvalidOperationException-Invalidcross-threadoperation分享

时间:2023-04-10 20:51:33 C#

.NETBackGroundWorker–InvalidOperationException:InvalidOperationException:Invalidcross-threadoperation我有一个用.NETWinforms编码的项目。我需要实施数据挖掘操??作,将文本打印到TextBox并更新进度。我试着用BackgroundWorker来做,但它抛出了一个InvalidOperationException(无效的跨线程操作:控制'xxxxx'从创建它的线程以外的线程访问)为了缩小问题的潜在原因,我开始了具有以下内容的新项目:按钮-启动BackgroundWorker标签-打印文本。和进度条。然而,结果是一样的。我搜索了SOF并被告知要使用委托,但我对此并不熟悉。这是抛出错误的代码显示示例:usingSystem;使用System.Collections.Generic;使用System.ComponentModel;namespaceTestProject{publicpartialclassForm1:Form{privatereadonlyBackgroundWorker_bw=newBackgroundWorker();publicForm1(){InitializeComponent();_bw.DoWork+=名册工作;_bw.ProgressChanged+=BwProgressChanged;_bw.RunWorkerCompleted+=BwRunWorkerCompleted;_bw.WorkerReportsProgress=true;_bw.WorkerSupportsCancellation=false;}privatevoidRosterWork(objectsender,DoWorkEventArgsdoWorkEventArgs){for(inti=0;i<1000;i++){label1.Text=i.ToString();_bw.ReportProgress(Convert.ToInt32((i*(100/1000))));}}privatevoidBwProgressChanged(objectsender,ProgressChangedEventArgse){progressBar1.Value=e.ProgressPercentage;}privatevoidbtnStart_Click(objectsender,EventArgse){progressBar1.Show();_bw.RunWorkerAsync();}privatevoidBwRunWorkerCompleted(objectsender,RunWorkerCompletedEventArgse){progressBar1.隐藏();更新:我遵循了JonSkeet的回答,它确实适用于我的测试项目,但回到我的真实项目,我的表格布局:Form-TabControl-Tab1-Tab1Panel-TextBox1reachs当这一行:TextBoxtxtbox1=newTextBox();Tab1Panel.Controls.Add(txtbox1);当我以编程方式将文本框添加到面板控件时,错误仍然存??在最后,我替换为:if(Tab1Panel.InvokeRequired)Tab1Panel.Invoke((MethodInvoker)delegate{Tab1Panel.Controls.Add(txtbox1);});否则Tab1Panel.Controls.Add(txtbox1);一切正常。如何判断一个控件是否为InvokeRequired,控件是否指定?这是问题所在:label1.Text=i.ToString();您正在尝试更改未在UI线程上运行的BackgroundWorker的标签文本。BackgroundWorker在那里完成所有非UI工作,使用ReportProgress定期“返回”到UI线程并使用您正在取得的进展更新UI。因此,您需要更改BwProgressChangedlabel1.Text,或者您需要像使用任何其他后台线程一样使用Control.Invoke/BeginInvoke://不要在lambda表达式中捕获循环变量...intcopy=i;操作updateLabel=()=>label1.Text=copy.ToString();label1.BeginInvoke(updateLabel);有关复制部分的更多信息,请参阅EricLippert的博客文章“闭环变量被认为是有害的”。在这种特殊情况下,这只是一个问题,因为我正在使用BeginInvoke。这可以更改为:ActionupdateLabel=()=>label1.Text=i.ToString();label1.调用(更新标签);...但现在后台工作人员将始终等待UI继续前进,这在现实生活中通常不是您想要的。我通常更喜欢BeginInvoke而不是Invoke。使用这段代码我会工作BeginInvoke((MethodInvoker)delegate{TextBox1.Text+="yourtexthere";});您正在从backgroundworker线程访问您的标签-已经在GUI线程上创建。不允许从创建控件的线程以外的线程访问Windows控件;因此你得到了例外。您不应直接访问标签,而应从您的线程中引发一个事件,并确保您在正确的线程上调用它-它向UI发出信号,以便您可以更改标签的内容。您必须从创建它们的线程中执行控件的方法。要从其他线程更新它们,请使用Invoke。可以在此处找到有关如何执行此操作的示例。您还应该阅读MSDN上的使用窗体和控件进行多线程处理。以上就是C#学习教程:.NETBackGroundWorker–InvalidOperationException:Thecross-threadoperationisinvalidandshared.如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处: