The calling thread cannot access this object - Tim

2019-10-03 06:08发布

问题:

This question already has an answer here:

  • Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on 21 answers
  • How to deal with cross-thread access exceptions? 3 answers

I am setting up a Timer within a method with an interval of 1000 so that every second it will type another corresponding character into a Textbox (pretty much automating typing). When I check for _currentTextLength == _text.Length I get the threading error "The calling thread cannot access this object because a different thread owns it."

 public void WriteText(string Text)
    {
        timer = new Timer();

        try
        {
            _text = Text;
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed_WriteText);
            timer.Interval = 1000;
            timer.Enabled = true;
            timer.Start();
        }
        catch
        {
            MessageBox.Show("WriteText timer could not be started.");
        }
    }
    // Write Text Timer Event
    void timer_Elapsed_WriteText(object sender, ElapsedEventArgs e)
    {
        TextBoxAutomationPeer peer = new TextBoxAutomationPeer(_textBox);
        IValueProvider valueProvider = peer.GetPattern(PatternInterface.Value) as IValueProvider;

        valueProvider.SetValue(_text.Substring(0, _currentTextLength));
        if (_currentTextLength == _text.Length) // Error here
        {
            timer.Stop();
            timer = null;
            return;
        }

        _currentTextLength++;
    }

The variable _text is a private class variable and so is _currentTextLength. _textBox is self explanatory.

Any way to solve this?

回答1:

Use a DispatcherTimer instead of a Timer.

A timer that is integrated into the Dispatcher queue which is processed at a specified interval of time and at a specified priority.

Should solve your problem.



回答2:

this simply means that you are trying to access some UI element from a thread other then it was created on. To overcome this you need to access it like this

this.Dispatcher.Invoke((Action)(() =>
    {
        //access it here
    }));

Note: If you want to check whether you can access it normally or not you can use this

Dispatcher.CheckAccess