Reputation: 131
I'm using C# wpf and want to take a camera picture and then after completion event call - change some controls in MainWindow. The issue is event is called in different thread than main one, and in order to run my NextState function (changing some controls) it needs to be the main thread (otherwise i get message box with warning and nothing happens). Here is my code:
public partial class PhotoCapture : UserControl
{
private bool ready;
private System.Timers.Timer timer;
private readonly Object lockObj = new Object();
public PhotoCapture(PhotoCaptureState photoCaptureState)
{
InitializeComponent();
ready = false;
PictureManager.LoadCompleted += PictureManager_LoadCompleted;
CameraManager.TakePicture();
timer = new System.Timers.Timer(200);
timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
timer.Enabled = true;
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
bool change = false;
lock(lockObj)
{
if (ready)
{
change = true;
}
}
if (change)
{
MessageBox.Show("ready");
timer.Enabled = false;
PictureManager.LoadCompleted -= PictureManager_LoadCompleted;
NextState();
}
}
private void PictureManager_LoadCompleted()
{
lock (lockObj)
{
ready = true;
}
}
private void NextState()
{
MainWindow wnd = (MainWindow)Application.Current.MainWindow;
App app = (App)wnd.contentControl.Content;
app.NextState();
}
}
What's interesting is I get a couple of "ready" message boxes and looks like NextStage isn't executed at all. I have no idea why it behaves like this. I would appreciate any help
Upvotes: 1
Views: 66
Reputation: 4138
You are correct, it's executed on a different thread.
You could invoke the NextState()
method on the main thread using the Dispatcher
.
Dispatcher.Invoke(() = > NextState());
Upvotes: 1
Reputation: 3751
A background thread that is spun off from the main UI thread cannot update the contents of the element that was created on the UI thread. In order for the background thread to access the property of the UI, the background thread must delegate the work to the Dispatcher associated with the UI thread.
In your Timer_Elapsed
class you need to Invoke the dispatcher to do your UI work. You can read about Dispatcher
here.
OR
Or you can try using DispatcherTimer
. DispatcherTimer fires its Tick event on the UI thread, you can do anything you want with the UI. You can see the examples here.
Upvotes: 2