Я получаю ошибку об использовании другого потока? - PullRequest
1 голос
/ 02 января 2012

Когда я нажимаю кнопку 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 ]

4 голосов
/ 02 января 2012

Описание

Вы должны использовать Invoke, чтобы гарантировать, что поток пользовательского интерфейса (поток, создавший ваш элемент управления) выполнит это.

1. Если вы работаете с Windows Forms, сделайте это

Пример

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 Forms

WPF

1 голос
/ 02 января 2012

Я подозреваю, что вы используете System.Threading.Timer.Вы можете избежать операции с несколькими потоками, просто используя таймер Windows.Forms: http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx Этот таймер использует обычные сообщения, и событие происходит в том же потоке пользовательского интерфейса.Используемое событие больше не называется «Истек», но «Тик» читайте в документе здесь: http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.tick.aspx

1 голос
/ 02 января 2012

Логика, выполняемая в событии Elapsed для Timer, выполняется в отдельном потоке от остальной части вашего кода. Этот поток не может получить доступ к объектам в основном потоке / GUI.

Этот поток должен помочь вам узнать, как это сделать: Как обновить графический интерфейс из другого потока в C #?

...