当我单击我的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);
}
}
答案 0 :(得分:4)
您必须使用Invoke
来确保UI线程(创建控件的线程)将执行该操作。
private void ChangeContent()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(ChangeContent));
return;
}
_main.ContentPage.Children.Clear();
_main.ContentPage.Children.Add(_homeScreen);
}
private void _tm_Elapsed(object sender, ElapsedEventArgs e)
{
((Timer) sender).Enabled = false;
this.Dispatcher.Invoke(new Action(ChangeContent), null);
//MessageBox.Show("ok");
}
答案 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