1

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

1
  • It is executed in different thread, also made some testes and it constantly executes Timer_Elapsed in new thread (id of current thread is increasing) Commented May 4, 2018 at 18:50

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.