【问题标题】:I get an error about using a different thread?我收到关于使用不同线程的错误?
【发布时间】:2012-01-02 10:39:08
【问题描述】:

当我单击我的 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);
    }
}

【问题讨论】:

  • 你在使用 System.Windows.Forms.Timer 吗?
  • 为避免跨线程操作,考虑使用 System.Windows.Forms.Timers
  • System.Windows.Forms。我找不到计时器:s
  • 但是我没有 Elapsed 属性和我当前使用的其他属性?

标签: c# user-controls timer childwindow


【解决方案1】:

说明

您必须使用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

【讨论】:

  • 抱歉,我找不到 InvokeRequired 的正确命名空间,我尝试了 MSDN 站点上的命名空间:s
  • InvokeRequired 是任何控件、用户控件、表单等的一部分。所以你可以做this.InvokeRequired...这不可用吗?
  • 这很奇怪。我复制了你的代码,它工作正常。您使用的是哪个版本的 .NET?
  • 但这是一个用户控件而不是表单或页面?
  • 您的UserControl 来自smartHome2011.FramePages 对吗?我不能给你更多帮助,因为我不知道smartHome2011.FramePages.UserControl 是什么。如果您的 UserControl 放置在 Windows 窗体上,请尝试此操作。 (this.Parent as System.Windows.Forms.Form).InvokeRequired.
【解决方案2】:

TimerElapsed 事件中执行的逻辑在与其余代码不同的线程上运行。此线程无法访问主/GUI 线程上的对象。

这个帖子应该可以帮助您了解如何做到这一点:How to update the GUI from another thread in C#?

【讨论】:

    【解决方案3】:

    我怀疑您使用的是 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

    【讨论】:

    • 使用 System.Timers;这是一样的吗?
    猜你喜欢
    • 2021-02-13
    • 2017-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多