4

我不断得到

Cross-thread operation not valid: Control 'keyholderTxt' accessed from a thread other than the thread it was created on.

关于项目中各种形式的各种控件,我用谷歌搜索了很多关于如何从各种线程访问内容的回复,但据我所知,我没有在我的项目中使用任何其他线程,并且更改代码中数百个可能的地方将是难以管理的。

它从来没有发生过,只是因为我添加了各种看似无关的代码。我包含了一个我得到以下错误的地方的示例,但它在整个解决方案的很多地方都发生了。

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 窗体应用程序。

4

4 回答 4

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();
   // ...
}
于 2013-08-28T12:05:08.683 回答
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();
于 2013-08-28T12:03:37.530 回答
1

你检查过VS中的线程面板吗?

于 2013-08-28T11:59:35.077 回答
1

_Timer( )的回调void _Timer_Tick(object sender, EventArgs e)发生在后台线程上。如果您希望回调位于 UI 线程上,请确保使用 a 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()));
}
于 2013-08-28T11:59:35.203 回答