locked
How are Background Tasks ( with ControlChannelTrigger and StreamSocket ) intended to work RRS feed

  • Question

  • I'm building an Metro XMPP Client and therefore I wanted to use Background Tasks with ControlChannelTrigger and StreamSockets,

    I read that an app will be suspended after a certain delay, and that in suspended mode it doesn't run code.
    My app is receiving XMPP Messages with LoadAsync from a DataReader and issues a toast notification with the content all from within the Application class.

    The app now has lock-screen rights, a ControlChannelTrigger and a background task, it shows notifications when I suspend it, when I close it ( Alt+F4 ) and when I have other apps started.

    What I don't understand is why my XMPP handler code is running even tough it is in the Main App, which should be stopped when it is suspended. The background task only informs me that there was data on the socket.

    Thanks,

    Paul

    Monday, June 18, 2012 7:51 PM

Answers

  • Hi,

    If your application is suspended when the background task is triggered, it will be launched automatically (but not brought to foreground). You can also host the background task in the system process BackgroundTaskHost.exe (certain types of triggers requires this kind of host). I would like to suggest you to check http://blogs.msdn.com/b/windowsappdev/archive/2012/05/24/being-productive-in-the-background-background-tasks.aspx for more information.

    Best Regards,

    Ming Xu.


    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework

    • Marked as answer by Paul Freund Tuesday, June 19, 2012 10:36 AM
    Tuesday, June 19, 2012 10:21 AM
    Moderator
  • Hi, Paul.

    Short answer: The application receives the data from the read complete handler of the StreamSocket.

    A bit more background about how things work behind the scenes: When an incoming message is received by the TCPIP stack for the transport (StreamSocket in your case) that was registered with the ControlChannelTrigger, Windows will indicate the data through the transport's read completion handler. However, as your app process is suspended initially, Windows will unsuspend the process using the Push Notification task that the app registered with the controlchanneltrigger. 

    Though the process is unsuspended, the UI threads may still be suspended. So any access to the UI will hang the app unless the app is brought to the foreground by the user. However, other threads such as those in the MTA can execute at this point. This means the app can retrieve the data or any error messages (such as if the socket was reset by the peer), through the read completion handler associated with the StreamSocket (or other supported transports). It is important to note that the Run method of the app's PushNotificationTask will not be executing at this point. This is because Windows internally synchronizes and blocks on the read completion handler to process the data/error received from the socket and then queue /store it in an appropriate data structure (not affinitized with UI STA). CoreApplication's property bag is one such example where the data may be stored. Once this is done, the app must to do two things: 1) Post another read and 2) Return control from the completion handler. The PushNotificationTask's Run method will now start to execute (it is important to meet the previous 2 conditions for the Run method to begin execution). Inside the Run method, the app can dequeue any stored data/error that was retrieved by the completion handler previously and process it. This may mean invoking APIs such as Toast notifications to alert user of an incoming phone call.

    A side note since I see you mentioned using DataReader in your question: Using await OR DataReader's LoadAsync for reading the data/error from the transport will not guarantee the synchronization described above. A reliable way to do that will be the raw async model against the streamsocket to retrieve the IBuffer from the stream. A DataReader instance can then be constructed based on this IBuffer pointer (DataReader.FromBuffer). We will be publishing the updated SDK samples soon that hopefully will make it easier to get such questions answered.

    Thanks,

    -Poorna Gaddehosur

    Thursday, July 19, 2012 6:26 AM

All replies

  • I also found this thread, in which there is described how to get the app context, it is stated that the app . there is a quote:

    "No, I meant your app has to handle the data in the background task. You can process your data in the background task before the user clicks on hte notification."

    Where ist the data meant to be received and processed? I don't really understand how this concept shall work as I can run code in the main app even if it shouldn't run.
    Am I supposed to handle only the package receive in the app and the parsing in the background? 

    clarification would be very nice.

    Thanks,

    Paul

    Tuesday, June 19, 2012 7:10 AM
  • Hi,

    If your application is suspended when the background task is triggered, it will be launched automatically (but not brought to foreground). You can also host the background task in the system process BackgroundTaskHost.exe (certain types of triggers requires this kind of host). I would like to suggest you to check http://blogs.msdn.com/b/windowsappdev/archive/2012/05/24/being-productive-in-the-background-background-tasks.aspx for more information.

    Best Regards,

    Ming Xu.


    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework

    • Marked as answer by Paul Freund Tuesday, June 19, 2012 10:36 AM
    Tuesday, June 19, 2012 10:21 AM
    Moderator
  • Hi, Paul.

    Short answer: The application receives the data from the read complete handler of the StreamSocket.

    A bit more background about how things work behind the scenes: When an incoming message is received by the TCPIP stack for the transport (StreamSocket in your case) that was registered with the ControlChannelTrigger, Windows will indicate the data through the transport's read completion handler. However, as your app process is suspended initially, Windows will unsuspend the process using the Push Notification task that the app registered with the controlchanneltrigger. 

    Though the process is unsuspended, the UI threads may still be suspended. So any access to the UI will hang the app unless the app is brought to the foreground by the user. However, other threads such as those in the MTA can execute at this point. This means the app can retrieve the data or any error messages (such as if the socket was reset by the peer), through the read completion handler associated with the StreamSocket (or other supported transports). It is important to note that the Run method of the app's PushNotificationTask will not be executing at this point. This is because Windows internally synchronizes and blocks on the read completion handler to process the data/error received from the socket and then queue /store it in an appropriate data structure (not affinitized with UI STA). CoreApplication's property bag is one such example where the data may be stored. Once this is done, the app must to do two things: 1) Post another read and 2) Return control from the completion handler. The PushNotificationTask's Run method will now start to execute (it is important to meet the previous 2 conditions for the Run method to begin execution). Inside the Run method, the app can dequeue any stored data/error that was retrieved by the completion handler previously and process it. This may mean invoking APIs such as Toast notifications to alert user of an incoming phone call.

    A side note since I see you mentioned using DataReader in your question: Using await OR DataReader's LoadAsync for reading the data/error from the transport will not guarantee the synchronization described above. A reliable way to do that will be the raw async model against the streamsocket to retrieve the IBuffer from the stream. A DataReader instance can then be constructed based on this IBuffer pointer (DataReader.FromBuffer). We will be publishing the updated SDK samples soon that hopefully will make it easier to get such questions answered.

    Thanks,

    -Poorna Gaddehosur

    Thursday, July 19, 2012 6:26 AM
  • Thank you very much Poorna !

    In the meantime my application works as I intended, the only thing that differs from you description is that I process the buffer I have read directly after the read of the socket. 

    In that case it is read the data , put it in the parser, which puts it in a token and put the token in a queue in the CoreApplication properties and invoke a notification if needed. I don't do anything in the  Run function of the BackgroundTask, this allows me to encapsulate the XMPP module very good. If you would say that it is not a good idea to do all that processing I would only read the data and trigger parsing from the ControlChannel. 

    I recently inspected the apps performance and it runs like a charm, also the app certification kit passed multiple times so I think my backend is good to go :)

    Best Regards,

    Paul

    Thursday, July 19, 2012 6:46 AM
  • Hi Paul,

    Sure, there are multiple ways to solve this but please note that the duration of Run method in the push notification task determines whether your process is suspended or not. If you return control from the Run method too early (while you are parsing the data etc.), your process may get suspended again and you will not be able to indicate the incoming message.

    Thanks,

    -Poorna Gaddehosur

    Thursday, July 19, 2012 7:23 PM