none
SkeletalViewer | Update method? RRS feed

  • Question

  • Hey guys, I am kind of confused, cause I am searching a way, how to change the code of skeletalviewer, so that I have something like an update method that is called 30times per second.

    What I am actually planning todo is to enlarge the window of the sample and to bring in an other videostream, but I cant acces this stream via eventhandler, i need to poll it and ask like 30times per second if there is a new image ready...

     

    Thanks for suggestions.

    (Actually the other stream I use was planned to run in a form (windows.forms) there I had an update method...)

    Monday, September 19, 2011 1:21 PM

Answers

  • Dear Eddy,

     EDIT:4

    You can scroll down to  ____ ##### ____ there I made a new update!

    [Old]

    right now, I am having following things:

    Change App.xaml the line startupuri to

    Startup="App_Startup" >

     

    App.xaml.cs

     

        public partial class App : Application
        {
            /// <summary>
            /// This event is used to synchronize between MainController and View
            /// </summary>
            private Synchronization.SyncEvents ViewMainControllerSyncEvents;
            void App_Startup(object sender, StartupEventArgs e)
            {
                ViewMainControllerSyncEvents = new Synchronization.SyncEvents();
    
                // Application is running
                System.Diagnostics.Debug.WriteLine("StartUp");
    
                // Initializing WorkerThread 1 for the MainController
                System.Threading.Thread thread;
                thread = new System.Threading.Thread(startMainController);
                thread.Name = "MainController Thread";
    
                thread.Start();
    
                // Show the main window
                MainWindow mainWindow;
                mainWindow = new MainWindow(ViewMainControllerSyncEvents);
                mainWindow.Show();
    
            }
    
            private void startMainController()
            {
                MainController maincontroller = new MainController(ViewMainControllerSyncEvents);
                maincontroller.UpdateMethod();
            }

     

    MainController.cs
    class MainController 
    { 
    #region Fields 
    /// <summary> 
    /// This event is used to synchronize with the view 
    /// </summary> Synchronization.SyncEvents ViewSyncEvents; Synchronization.SyncEvents KinectManagerMainControllerSyncEvents; 
    #endregion 
    
    #region Constructor 
    /// <summary> 
    /// This is the constructor of the main controller. It initializes all other threads such as SkeletonManager and handles all data (e.g. video images from kinectmanager to view (MainWindow) ) 
    /// </summary> 
    /// <param name="sync">Synchronization construct used to synchronize with view like getting info about exiting from view or informing view about new video data available. (TODO: Add Queue for synchronizing data)</param> 
    public MainController(Synchronization.SyncEvents sync) 
    { ViewSyncEvents = sync; KinectManagerMainControllerSyncEvents = new Synchronization.SyncEvents(); 
    Thread kinectThread = new Thread(kinectMethod);
     kinectThread.Start(); } 
    #endregion 
    
    public void UpdateMethod() 
    { 
    System.Diagnostics.Debug.WriteLine("Entering MainController Thread"); 
    //Stays in this loop till exit event occured (through view!) 
    while (!ViewSyncEvents.ExitThreadEvent.WaitOne(0, false))
    //(WaitHandle.WaitAny(syncEvents.EventArray) != 1) 
    { 
    } 
    
    //TODO: Add method that sets all exitevents that other threads are informed about exiting! System.Diagnostics.Debug.WriteLine("Exiting MainController Thread"); 
    } 
    }
    but the problem still resists.

    I have no "Update method" in my mainwindow class.

    So how to check if new data is available?

    In my maincontroller class i have the update method, so here I can check for new data from kinectmanager or others.

    But how to implement this in view?

     

    Hope my code snippets are sufficient for you.

    Thanks in advance,

    Simon

    [/OLD]

     

     

    EDIT:4

    _____________________________________________________________________________________________________________

    #######################################################################################

    _____________________________________________________________________________________________________________

    Maybe I solved my problem with the update method.

    I knew, there could be a possibility to get a timer and make a update method that polls on things like "is there a new video image?", but I think this is a very unefficient way to do.

    So I was thinking about making the whole thing with eventhandler.

    I added this to my MainControllerClass on Top (in section #region Fields!)

            #region Fields
            // declare a delegate for the NewDataFromController event
            public delegate void NewDataFromControllerHandler(object sender, EventArgs e);
    
            // declare the NewDataFromController event using the NewDataFromControllerHandler delegate
            public static event NewDataFromControllerHandler NewDataFromController;
            
            /// <summary>
            /// This method fires new data event delegate. This method should be called 
            /// from producer if he wants to inform consumer about new data!
            /// </summary>
            public void OnNewDataFromController()
            {
                if (NewDataFromController == null)
                    throw new InvalidOperationException("The Handler must not be null! Please initialize it properly (new) before you call");
                NewDataFromController(this, new EventArgs());
            }
            #endregion
     
    So if I have new Data available in Controller, I call method OnNewDataFromController() what is firing the event.

    BUT: Who is listening to the event?

    I did NOT implement an handler in Controller class!

    I implemented it in an other object that is is another thread.

    I really hope this is thread safe. So check it out:

    go to MainWindow.g.cs

    and add this under class

        /// <summary>
        /// MainWindow
        /// </summary>
        [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
        public partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector {
    
    
            Synchronization.SyncEvents controllerSyncEvents;
    
            // Declare our delagate
            private MainController.NewDataFromControllerHandler newDataDelegate;


     

    NOW add this to initialize method
            /// <summary>
            /// Needed to implement Interfacemethod. Not used. Instead its used with overload constructor to initialize events for synchronization
            /// </summary>
            [System.Diagnostics.DebuggerNonUserCodeAttribute()]
            public void InitializeComponent() { }
    
            /// <summary>
            /// InitializeComponent
            /// </summary>
            [System.Diagnostics.DebuggerNonUserCodeAttribute()]
            public void InitializeComponent(Synchronization.SyncEvents sync) {
                if (_contentLoaded) {
                    return;
                }
                _contentLoaded = true;
                controllerSyncEvents = sync;
    
                // create a new delegate, instance and bind it
                // to the observer's bookpricechanged method
                newDataDelegate = new MainController.NewDataFromControllerHandler(this.NewDataFromControllerAvailable);
                //add the delegate to the event
                MainController.NewDataFromController += newDataDelegate;
    
                System.Uri resourceLocater = new System.Uri("/SkeletalViewer;component/mainwindow.xaml", System.UriKind.Relative);

    The code snippets above aren't completely new written, some stuff is from "old" source code, I just added some parts and showing in this section more than I added!

     

    Now go to MainWindow.cs and add this code snippet:

    private void NewDataFromControllerAvailable(object sender, EventArgs e)
    { 
    System.Diagnostics.Debug.WriteLine("Fired"); 
    }


    Everytime I have new data available in Controller I call there OnNewDataFromController which calls the event.

    Every object that has initialized an handler to this (+=new ...handler...(my_method);) will get an event in

    void my_method(object sender, EventArgs e)

    {

              //here we go

    }

     

    So hopefully I reached a new level today and can go futher ;-)

    If not, I will come back here,

     

    Simon





    Thursday, September 22, 2011 1:05 PM

All replies

  • To avoid receiving events from skeletal viewer, you could:

    1) remove the following 3 lines from Window_Loaded

    nui.DepthFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_DepthFrameReady);
                nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
                nui.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_ColorFrameReady);

    2) You can change the signature of nui_ColorFrameReady, nui_DepthFrameReady and nui_SkeletonFrameReady to

    void nui_ColorFrameReady(ImageFrame frame)
    void nui_DepthFrameReady (ImageFrame frame)
    void nui_SkeletonFrameReady (SkeletonFrame frame)

    These are now your "Update" methods.

    3) Poll for new frames every 30 milliseconds using

    ImageFrame videoFrame = nui.VideoStream.GetNextFrame(0);
    if (videoFrame != null) nui_ColorFrameReady(videoFrame);
    ImageFrame depthFrame = nui.DepthStream.GetNextFrame(0);
    if (depthFrame != null) nui_DepthFrameReady(depthFrame);
    SkeletonFrame skeletonFrame = nui.SkeletonEngine.GetNextFrame(0);
    if (skeletonFrame != null) nui_SkeletonFrameReady(skeletonFrame);

    Does that make sense?
    Eddy


    I'm here to help
    Monday, September 19, 2011 11:58 PM
  • Thank you for your quick reply.

     

    I will think about it and check, if I can use your thoughts.

    But thank you for sharing them and the code snippets.

    Anyway, very helpfull!!!

    Tuesday, September 20, 2011 12:36 PM
  • Hello Eddy, me again.

     

    I have a question,

    ist it possible to fire events through threads?

     

    Actually I have two threads, one that is getting 30 images per second through an eventhandler.

    The other thread is a system.windows inherited class.

    There I would like to listen to the eventhandler from the other thread.

    But again, there is no "Update Method" where I could check my queue (that I use to synchronize data between the two threads) for new data.

    I actually have written an eventclass, where I can signal if a new image is in the queue but I have no chance to check this event without any Update Method or eventhandler...

    The only thing I get from system.windows is Window_Loaded and Window_Closed...

     

    I really really hope you could help me.

    Threading is such an hard task and I really dont know if it even makes sense what I am thinking about...

     

    Thanks,

    Simon

    Wednesday, September 21, 2011 3:32 PM
  • Could you provide some of your code, with comments in the parts where you are confused, so I can try to help you out? I'm not sure at this point that I understand what your background thread is doing.

    To execute code in a main thread in WPF or WinForms, you can use SynchronizationContext objects (http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx). You can get the SynchronizationContext by calling SynchronizationContext.Current static property from main thread, and then you can pass this context to your background thread. Then the background thread can call SynchronizationContext.Post (or Send) like:

    context.Post(delegate
    {
        // Your code here. This code actually gets executed in the main thread.
    }, null);

    Hope this helps,
    Eddy 


    I'm here to help
    Wednesday, September 21, 2011 8:19 PM
  • Dear Eddy,

     EDIT:4

    You can scroll down to  ____ ##### ____ there I made a new update!

    [Old]

    right now, I am having following things:

    Change App.xaml the line startupuri to

    Startup="App_Startup" >

     

    App.xaml.cs

     

        public partial class App : Application
        {
            /// <summary>
            /// This event is used to synchronize between MainController and View
            /// </summary>
            private Synchronization.SyncEvents ViewMainControllerSyncEvents;
            void App_Startup(object sender, StartupEventArgs e)
            {
                ViewMainControllerSyncEvents = new Synchronization.SyncEvents();
    
                // Application is running
                System.Diagnostics.Debug.WriteLine("StartUp");
    
                // Initializing WorkerThread 1 for the MainController
                System.Threading.Thread thread;
                thread = new System.Threading.Thread(startMainController);
                thread.Name = "MainController Thread";
    
                thread.Start();
    
                // Show the main window
                MainWindow mainWindow;
                mainWindow = new MainWindow(ViewMainControllerSyncEvents);
                mainWindow.Show();
    
            }
    
            private void startMainController()
            {
                MainController maincontroller = new MainController(ViewMainControllerSyncEvents);
                maincontroller.UpdateMethod();
            }

     

    MainController.cs
    class MainController 
    { 
    #region Fields 
    /// <summary> 
    /// This event is used to synchronize with the view 
    /// </summary> Synchronization.SyncEvents ViewSyncEvents; Synchronization.SyncEvents KinectManagerMainControllerSyncEvents; 
    #endregion 
    
    #region Constructor 
    /// <summary> 
    /// This is the constructor of the main controller. It initializes all other threads such as SkeletonManager and handles all data (e.g. video images from kinectmanager to view (MainWindow) ) 
    /// </summary> 
    /// <param name="sync">Synchronization construct used to synchronize with view like getting info about exiting from view or informing view about new video data available. (TODO: Add Queue for synchronizing data)</param> 
    public MainController(Synchronization.SyncEvents sync) 
    { ViewSyncEvents = sync; KinectManagerMainControllerSyncEvents = new Synchronization.SyncEvents(); 
    Thread kinectThread = new Thread(kinectMethod);
     kinectThread.Start(); } 
    #endregion 
    
    public void UpdateMethod() 
    { 
    System.Diagnostics.Debug.WriteLine("Entering MainController Thread"); 
    //Stays in this loop till exit event occured (through view!) 
    while (!ViewSyncEvents.ExitThreadEvent.WaitOne(0, false))
    //(WaitHandle.WaitAny(syncEvents.EventArray) != 1) 
    { 
    } 
    
    //TODO: Add method that sets all exitevents that other threads are informed about exiting! System.Diagnostics.Debug.WriteLine("Exiting MainController Thread"); 
    } 
    }
    but the problem still resists.

    I have no "Update method" in my mainwindow class.

    So how to check if new data is available?

    In my maincontroller class i have the update method, so here I can check for new data from kinectmanager or others.

    But how to implement this in view?

     

    Hope my code snippets are sufficient for you.

    Thanks in advance,

    Simon

    [/OLD]

     

     

    EDIT:4

    _____________________________________________________________________________________________________________

    #######################################################################################

    _____________________________________________________________________________________________________________

    Maybe I solved my problem with the update method.

    I knew, there could be a possibility to get a timer and make a update method that polls on things like "is there a new video image?", but I think this is a very unefficient way to do.

    So I was thinking about making the whole thing with eventhandler.

    I added this to my MainControllerClass on Top (in section #region Fields!)

            #region Fields
            // declare a delegate for the NewDataFromController event
            public delegate void NewDataFromControllerHandler(object sender, EventArgs e);
    
            // declare the NewDataFromController event using the NewDataFromControllerHandler delegate
            public static event NewDataFromControllerHandler NewDataFromController;
            
            /// <summary>
            /// This method fires new data event delegate. This method should be called 
            /// from producer if he wants to inform consumer about new data!
            /// </summary>
            public void OnNewDataFromController()
            {
                if (NewDataFromController == null)
                    throw new InvalidOperationException("The Handler must not be null! Please initialize it properly (new) before you call");
                NewDataFromController(this, new EventArgs());
            }
            #endregion
     
    So if I have new Data available in Controller, I call method OnNewDataFromController() what is firing the event.

    BUT: Who is listening to the event?

    I did NOT implement an handler in Controller class!

    I implemented it in an other object that is is another thread.

    I really hope this is thread safe. So check it out:

    go to MainWindow.g.cs

    and add this under class

        /// <summary>
        /// MainWindow
        /// </summary>
        [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
        public partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector {
    
    
            Synchronization.SyncEvents controllerSyncEvents;
    
            // Declare our delagate
            private MainController.NewDataFromControllerHandler newDataDelegate;


     

    NOW add this to initialize method
            /// <summary>
            /// Needed to implement Interfacemethod. Not used. Instead its used with overload constructor to initialize events for synchronization
            /// </summary>
            [System.Diagnostics.DebuggerNonUserCodeAttribute()]
            public void InitializeComponent() { }
    
            /// <summary>
            /// InitializeComponent
            /// </summary>
            [System.Diagnostics.DebuggerNonUserCodeAttribute()]
            public void InitializeComponent(Synchronization.SyncEvents sync) {
                if (_contentLoaded) {
                    return;
                }
                _contentLoaded = true;
                controllerSyncEvents = sync;
    
                // create a new delegate, instance and bind it
                // to the observer's bookpricechanged method
                newDataDelegate = new MainController.NewDataFromControllerHandler(this.NewDataFromControllerAvailable);
                //add the delegate to the event
                MainController.NewDataFromController += newDataDelegate;
    
                System.Uri resourceLocater = new System.Uri("/SkeletalViewer;component/mainwindow.xaml", System.UriKind.Relative);

    The code snippets above aren't completely new written, some stuff is from "old" source code, I just added some parts and showing in this section more than I added!

     

    Now go to MainWindow.cs and add this code snippet:

    private void NewDataFromControllerAvailable(object sender, EventArgs e)
    { 
    System.Diagnostics.Debug.WriteLine("Fired"); 
    }


    Everytime I have new data available in Controller I call there OnNewDataFromController which calls the event.

    Every object that has initialized an handler to this (+=new ...handler...(my_method);) will get an event in

    void my_method(object sender, EventArgs e)

    {

              //here we go

    }

     

    So hopefully I reached a new level today and can go futher ;-)

    If not, I will come back here,

     

    Simon





    Thursday, September 22, 2011 1:05 PM