我收到有关使用其他线程的错误?

时间:2012-01-02 10:39:09

标签: c# user-controls timer childwindow

当我单击我的ActionButton时,会有一个启动的计时器,在3秒后,它必须触发一个方法来将当前的ContentPage更改为另一个页面。 但我收到一条消息:调用线程无法访问此对象,因为另一个线程拥有它。我不明白我做错了什么。但是,如果我将ChangeContent()方法放在click_event中,它可以工作,但是在_tm_elapsed中它会起作用吗?

using smartHome2011.FramePages;
using System.Timers;

public partial class AuthenticationPage : UserControl
{
    private MainWindow _main;
    private Storyboard _storyboard;
    private Timer _tm = new Timer();
    private HomeScreen _homeScreen = new HomeScreen();

    public AuthenticationPage(MainWindow mainP)
    {
        this.InitializeComponent();
        _main = mainP;
    }

    private void ActionButton_Click(object sender, System.EventArgs eventArgs)
    {
        _main.TakePicture();
        identifyBox.Source = _main.source.Clone();
        scanningLabel.Visibility = Visibility.Visible;
        _storyboard = (Storyboard) FindResource("scanningSB");
        //_storyboard.Begin();
        Start();
    }

    private void Start()
    {
        _tm = new Timer(3000);
        _tm.Elapsed += new ElapsedEventHandler(_tm_Elapsed);
        _tm.Enabled = true;
    }

    private void _tm_Elapsed(object sender, ElapsedEventArgs e)
    {
        ((Timer) sender).Enabled = false;
        ChangeContent();
        //MessageBox.Show("ok");
    }

    private void ChangeContent()
    {
        _main.ContentPage.Children.Clear();
        _main.ContentPage.Children.Add(_homeScreen);
    }
}

3 个答案:

答案 0 :(得分:4)

描述

您必须使用Invoke来确保UI线程(创建控件的线程)将执行该操作。

1。如果您正在执行Windows窗体,请执行此操作

示例

private void ChangeContent()
{
    if (this.InvokeRequired)
    {
        this.Invoke(new MethodInvoker(ChangeContent));
        return;
    }

    _main.ContentPage.Children.Clear();
    _main.ContentPage.Children.Add(_homeScreen);
}

2。如果您正在执行WPF,请执行此操作

private void _tm_Elapsed(object sender, ElapsedEventArgs e)
{
    ((Timer) sender).Enabled = false;
    this.Dispatcher.Invoke(new Action(ChangeContent), null);
    //MessageBox.Show("ok");
}

更多信息

Windows窗体

WPF

答案 1 :(得分:1)

Elapsed的{​​{1}}事件中执行的逻辑在与其余代码分开的线程上运行。该线程无法访问主/ GUI线程上的对象。

此主题应该可以帮助您了解如何执行此操作:How to update the GUI from another thread in C#?

答案 2 :(得分:1)

我怀疑您使用的是System.Threading.Timer。只需使用Windows.Forms计时器即可避免跨线程操作: http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx 该计时器使用常规消息,并且事件在UI的同一线程上出现。 要使用的事件不再称为“Elapsed”,但“Tick”会在此处阅读文档:http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.tick.aspx