我一直在
Cross-thread operation not valid: Control 'keyholderTxt' accessed from a thread other than the thread it was created on.
关于项目中各种表单的各种控件,我已经用Google搜索并发现了很多关于如何从各种线程访问内容的响应,但据我所知,我没有在我的项目中使用任何其他线程,并且要更改代码中数百个可能的位置将是无法管理的。
它从未发生过,只是因为我添加了似乎无关的各种代码。我在下面列出了错误的地方样本,但是在整个解决方案中已经发生了很多地方。
keyholderTxt.Text = "Keyholders Currently In:\r\n \r\n Nibley 1: + keyholders";
或者这是一个更好的例子,因为你可以看到从表单加载到错误所发生的一切:
private void Identification_Load(object sender, System.EventArgs e)
{
_Timer.Interval = 1000;
_Timer.Tick += new EventHandler(_Timer_Tick);
_Timer.Start();
txtIdentify.Text = string.Empty;
rightIndex = null;
SendMessage(Action.SendMessage, "Place your finger on the reader.");
if (!_sender.OpenReader())
{
this.Close();
}
if (!_sender.StartCaptureAsync(this.OnCaptured))
{
this.Close();
}
}
void _Timer_Tick(object sender, EventArgs e)
{
this.theTime.Text = DateTime.Now.ToString();
}
private void OnCaptured(CaptureResult captureResult)
{
txtIdentify.Clear();
//other stuff after the cross thread error
}
不关闭数据引导程序会导致这种错误吗?
我正在使用Windows窗体应用程序。
答案 0 :(得分:7)
我怀疑罪魁祸首是这样的:
if (!_sender.StartCaptureAsync(this.OnCaptured))
我不知道您正在使用的API,但基于名称,我认为回调方法(OnCaptured
)是在工作线程而不是UI线程上调用的。因此,您需要使用Invoke在UI线程上执行操作:
private void OnCaptured(CaptureResult captureResult)
{
if (InvokeRequired)
{
Invoke(new System.Action(() => OnCaptured(captureResult)));
return;
}
txtIdentify.Clear();
// ...
}
答案 1 :(得分:3)
好的,抓住这个。我看到你正在使用System.Windows.Forms.Timer
,正如下面提到的评论,它已经在UI线程上执行了。我以为你在使用System.Timers.Timer
。
计时器回调正在线程池线程上执行。您可以通过设置SynchronizingObject:
使其在UI线程上执行 _Timer.Interval = 1000;
_Timer.Tick += new EventHandler(_Timer_Tick);
_Timer.SynchronizingObject = this;
_Timer.Start();
答案 2 :(得分:1)
你检查过VS中的线程面板吗?
答案 3 :(得分:1)
来自_Timer
(void _Timer_Tick(object sender, EventArgs e)
)的回调发生在后台线程上。如果您希望回调在UI线程上,请确保使用System.Windows.Forms.Timer
(假设您使用的是Windows窗体)。
正如评论者所说。检查调试器中的线程窗口,检查发生异常的线程。
或者,对于Windows窗体,请尝试使用
void _Timer_Tick(object sender, EventArgs e)
{
this.BeginInvoke(new Action(() => this.theTime.Text = DateTime.Now.ToString()));
}
对于WPF,试试这个
void _Timer_Tick(object sender, EventArgs e)
{
this.Dispatcher.BeginInvoke(new Action(() => this.theTime.Text = DateTime.Now.ToString()));
}
如果this
不是控件或窗口而你是WPF
void _Timer_Tick(object sender, EventArgs e)
{
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => this.theTime.Text = DateTime.Now.ToString()));
}