交叉线程错误,但不使用线程

时间:2013-08-28 11:43:19

标签: c# .net multithreading textbox

我一直在

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

4 个答案:

答案 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)

来自_Timervoid _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()));
}