locked
How to delay 3 seconds and do NOT to hang Current Metro Windows?

    Question

  • My Scenario is like that:

    There is a interface in my WinRT Components ( using C++ ), I do need to query some status each 20ms, and after 3s, Stoping query and return result to Metro windows by callback function, but this operation DO NOT hang Metro windows( using C#).

    so How can I implement this function?

    Friday, July 20, 2012 6:27 AM

Answers

  • Hello,

    I found two way to achieve this,

     1. You can use Background task, using the TimeTrigger as trigger. Please follow these document.
     http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh977055.aspx
     http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.applicationmodel.background.timetrigger.aspx
     
     2. You can use a loop, in every loop you can sleep 20ms and run this loop 150 times.
     
    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    • Marked as answer by Jesse Jiang Thursday, August 2, 2012 7:22 AM
    Monday, July 23, 2012 8:35 AM
  • Hi Henador:

    In Win8 Metro WinRT Components, it don't allow that syntax like that: _beginthreadex, WatiForSingleObject, e.g.;

    and I finally got the right way to implement those requirement:

    ////////////////////////////////////////

    static void OnTimerChanged(ThreadPoolTimer^ DelayTimer);
    static TimerElapsedHandler^ g_hTimerElapsed = ref new TimerElapsedHandler(OnTimerChanged);
    static ThreadPoolTimer^ g_DelayTimer = nullptr;

    static void OnTimerChanged(ThreadPoolTimer^ DelayTimer)
    {
     try
     {
      //Do your jobs
     }
     catch( ... )
     {
     }
    }

    static void ThreadProc(  )
    {
     try
     {
      
      TimeSpan delay;
      delay.Duration = TIME_REVOLUTION * 10000;//TIME_REVOLUTION is your delay times, unit is second.
      g_lpfCallback = lpCallback;
      g_lpfProtocol = lpProtocol;

      if (g_DelayTimer == nullptr )
      {  
       g_DelayTimer = ThreadPoolTimer::CreatePeriodicTimer( g_hTimerElapsed, delay);
      }
     }
     catch( ... )
     {
     }
    }

    static concurrency::task<void> StartThreadProcTask(  )
    {
     auto workItemHandler = ref new WorkItemHandler([=](IAsyncAction^)
        {
            try
            {
       ThreadProc( lpProtocol, lpCallback );
      }
            catch (...) { }

        }, CallbackContext::Same);//I don't know what means about "Same" and "Any";

        ThreadPool::RunAsync(workItemHandler, WorkItemPriority::Normal, WorkItemOptions::TimeSliced);

     return concurrency::task<void>( );
    }

     
    • Proposed as answer by Jesse Jiang Wednesday, August 1, 2012 9:06 AM
    • Marked as answer by Jesse Jiang Thursday, August 2, 2012 7:22 AM
    Wednesday, August 1, 2012 7:45 AM

All replies

  • Seems like it would be easier to:

    1. Have a C++ component that only does the status query (hardware, I assume?)

    2. Use CreatePeriodicTimer in C# and have your C# WorkItem call the C++ component periodically

    That way you keep all the timer manipulation and notification stuff in C#.

    Friday, July 20, 2012 12:02 PM
  • Hello,

    I found two way to achieve this,

     1. You can use Background task, using the TimeTrigger as trigger. Please follow these document.
     http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh977055.aspx
     http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.applicationmodel.background.timetrigger.aspx
     
     2. You can use a loop, in every loop you can sleep 20ms and run this loop 150 times.
     
    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    • Marked as answer by Jesse Jiang Thursday, August 2, 2012 7:22 AM
    Monday, July 23, 2012 8:35 AM
  • Hi Henador:

    I don't think your idea is suitable for my condition, I need to encapsulate this (including timer and query) to WinRT components and privode to metro.

    Hi Jesse:

    I think the second way is suitable for my condition; but, problem is how to implement a loop in C++ WinRT? As I known, there must be thread. and the point is here is a timer in loop; I found the timer is big different with Win32 API; Oppss, I'm not good at this.

    Is that a correct way to create timer?

    "DelayTimer =

    Windows::System::Threading::

    ThreadPoolTimer::CreateTimer

    (refnewWindows::System::Threading::TimerElapsedHandler(timerDelegate), delay);"

    Monday, July 23, 2012 9:02 AM
  • Note that I'm a newbie to WinRT/Metro so I don't know if this will work properly! If you're going to stay in C++ for the whole thing, I would implement the C++ part of Jesse's #2 suggestion like this:

    static HANDLE hEventAbort;
    
    unsigned int _stdcall QueryThreadProc( void *args )
     {
      for( int i = 0; i < 150; i++ )
       {
        DWORD dwrc;
    
        dwrc = WaitForSingleObjectEx( hEventAbort, 20, FALSE );
        if( dwrc == WAIT_OBJECT_0 )
         {
          return 1; // aborted
         }
    
        // do query here, notify c# and return if TRUE
    
       }
    
      // notify c# of timeout
      return 2;
     }
    
    
    void StartQueryLoop()
     {
      hEventAbort = CreateEventEx( 0, 0, 0, 0 );
      _beginthreadex( 0, 0, QueryThreadProc, 0, 0, 0 );
     }
    
    
    void AbortQueryLoop()
     {
      SetEvent( hEventAbort );
     } 
    

    I have no idea how to notify a C# app from a thread in a C++ component.

    Tuesday, July 24, 2012 2:43 PM
  • Hi Henador:

    In Win8 Metro WinRT Components, it don't allow that syntax like that: _beginthreadex, WatiForSingleObject, e.g.;

    and I finally got the right way to implement those requirement:

    ////////////////////////////////////////

    static void OnTimerChanged(ThreadPoolTimer^ DelayTimer);
    static TimerElapsedHandler^ g_hTimerElapsed = ref new TimerElapsedHandler(OnTimerChanged);
    static ThreadPoolTimer^ g_DelayTimer = nullptr;

    static void OnTimerChanged(ThreadPoolTimer^ DelayTimer)
    {
     try
     {
      //Do your jobs
     }
     catch( ... )
     {
     }
    }

    static void ThreadProc(  )
    {
     try
     {
      
      TimeSpan delay;
      delay.Duration = TIME_REVOLUTION * 10000;//TIME_REVOLUTION is your delay times, unit is second.
      g_lpfCallback = lpCallback;
      g_lpfProtocol = lpProtocol;

      if (g_DelayTimer == nullptr )
      {  
       g_DelayTimer = ThreadPoolTimer::CreatePeriodicTimer( g_hTimerElapsed, delay);
      }
     }
     catch( ... )
     {
     }
    }

    static concurrency::task<void> StartThreadProcTask(  )
    {
     auto workItemHandler = ref new WorkItemHandler([=](IAsyncAction^)
        {
            try
            {
       ThreadProc( lpProtocol, lpCallback );
      }
            catch (...) { }

        }, CallbackContext::Same);//I don't know what means about "Same" and "Any";

        ThreadPool::RunAsync(workItemHandler, WorkItemPriority::Normal, WorkItemOptions::TimeSliced);

     return concurrency::task<void>( );
    }

     
    • Proposed as answer by Jesse Jiang Wednesday, August 1, 2012 9:06 AM
    • Marked as answer by Jesse Jiang Thursday, August 2, 2012 7:22 AM
    Wednesday, August 1, 2012 7:45 AM