locked
C#/C++ Callback AccessViolationException when Application is pushed to background (ex. Alt-Tab)

    Question

  • Hey Everyone,

    I am having an issue with my Metro application and this only happens during the application being switched to a background running state for example hitting Alt-Tab. It uses a C++ unmanaged DLL to run some code and then references a callback to invoke a delegate in C#. This as of last night worked perfectly, however, one small thing, it blocked and froze the UI thread.

    The next step was to encapsulate the call using an Async method via Task.Run<T>(Action). After doing this, the UI thread was relieved and I was still able to retrieve the callback coming from the DLL running on another thread. So far so good, until I Alt-Tabbed away I got an AccessViolationException. My guess is based on what I've been able to put together on how the new Windows 8 mechanisms work, when an app looses visibility, all current operations/tasks are suspended. My DLL is still however running on it's thread and when it gets time to reference and send data back through the function pointer, Windows is saying "I don't think so" and the memory is now protected thus creating the AccessViolationException in the C# Metro app and bringing down the house.

    I tried doing things like creating event handlers for Window.Current.VisibilityChanged, ...Suspending, etc. and cant catch the change before the app goes bye-bye to the background. The event handler cant even hit because my guess the other task is still rocking along before the trigger is activated and hits it's issue before I can catch it and end it manually.

    Some sample code on how I did this is below but my question is, in specific cases where you need to run a Task or a method right as the app detects it will move its state into the background, how do you go about doing so? Also I have seen things like BackgroundTasks that work off of a trigger but none of the triggers seemed to be a BackgroundStateActivated or a ForegroundStateResumed. What are my options for controlling this being able to manage it properly?

     

    Here is the DLLImport and callback in C#...

    /// <summary> /// The native methods in the DLL's unmanaged code. /// </summary> internal static class UnsafeNativeMethods { const string _dllLocation = @"External\UnmanagedLayer.dll"; public delegate void CallbackFunction(int Value); public static CallbackFunction Callback = (Value) => { // Some Callback Functionality... }; [DllImport(_dllLocation)] private static extern void StartTask(CallbackFunction Function); [DllImport(_dllLocation)] private static extern void EndTask(); public static async void StartAsync() { await Task.Run(() => { StartTask(Callback); }); } public static async void EndAsync() { await Task.Run(() => { EndTask(); }); } }

    Here is the C++ where I declare the task (its an audio recording/processing task)...

    // DLL Exports
    __declspec(dllexport) void __stdcall StartTask(CallbackFunction Callback)
    {
    	if (pAudioSink == NULL)
    		pAudioSink = new AudioSink();
    	pAudioSink->Function = Callback;
    	pAudioSink->StartCapture();
    	RecordAudioStream(pAudioSink);
    }
    
    __declspec(dllexport) void __stdcall EndTask()
    {
    	if (pAudioSink != NULL)
    	{
    		pAudioSink->EndTask();
    	}
    }

    And this is how the C++ equivalent callback is declared...

    // Function pointer type for AudioSink to call to C#
    typedef void (__stdcall *CallbackFunction)(short);

    Like I said, this all worked great until the app goes into a Background state, if any of you can help make this more clear and how to properly handle this scenario, it would be much appreciated. Take care and have a great day!

    Thank You!

    Matthew Castellana

    Sunday, July 22, 2012 2:07 AM

Answers

  • Okay Matthew,

    I've been working with the audio architect to understand all of our options for working with audio in the background. If you are writing a communications app such as VO/IP, etc. we do have low level hooks to allow you to continue to run in the background. Since background tasks can drain the battery rather quickly I would recommend that you avoid doing this if possible.

    Here is a link to a sample that should show you all you need to do:

    http://code.msdn.microsoft.com/windowsapps/Audio-hardware-offload-280dc923

    Thanks,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Monday, July 30, 2012 9:11 PM
    Moderator

All replies

  • Hello Matthew,

    Are you trying to record audio in the background when the app gets suspended? If this is what you are trying to accomplish what underlying audio technology are you using to record the data?

    Thanks,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Tuesday, July 24, 2012 12:03 AM
    Moderator
  • Hey James,

    Thanks for the reply! Yes, the AccessViolationException is being caused when I'm in the process of capturing audio and the app goes into it's suspended state (the C++ DLL is doing the capturing). This right now is a testing ground for an app planned for the Win 8 launch and the reason why I am calling into a DLL to handle the audio processing is because the C# MediaCapture API doesn't support PCM as a format and you cannot obtain the raw bytes coming from the microphone. Also MS hasn't put out much documentation yet on creating your own MediaSinks for the API. From a lot of different threads out there on the internet, various MS MVPs state to use C++ and WASAPI to handle this level of processing to get access to the raw audio data in the lowest latency possible. In the code I posted above, the C++ RecordAudioStream function is using the code from the following example http://msdn.microsoft.com/en-us/library/windows/desktop/dd316756(v=vs.85).aspx on how to record to a stream using WASAPI. During the capture process, I do some processing on the audio sample data and fire a Callback to notify the C# Metro app with the results as they come in.

    Thanks,

    Matthew Castellana

    Tuesday, July 24, 2012 2:05 AM
  • James,

    My application does not support playback and cannot use that attribute as it is strictly WASAPI. I spent a great deal of time working on this Metro app for the Windows Marketplace and it is a shame none of this is documented yet with Windows 8 around the corner and the Marketplace landing within the next 2 weeks for paid apps/games. Is this documentation going to land before the launch of Windows 8? I would assume since background processing is a core part of the new Metro platform, that this would be launching shortly...

    My DLL works and all I am trying to do is to be able to process the Raw audio coming from a specific recording input. All I need is direct access to the bytes. I know this is not currently possible in .Net (in Raw format) or is maybe, but also hindered due to a lack of documentation with creating MediaSinks for the MediaCapture API. I would like to know what options I have to make sure I can launch this application and a proper response on how I can go about this would be extremely appreciated. James, even if this isn't yet documented, what documentation is currently available on setting up background processes in Metro applications?

    Like I said in my previous post, various MVPs and MS employees stated in numerous threads to go this route for Metro application designs that needed access to the raw audio data. The question is, what is the proper step to bring it together properly when handling stream processing in the background? I am sure there are many developers out there that are taking this advice on processing audio and running into the same brick wall as I am. Are there any ways to simply run code before the application enters it's background state? If I can simply fire off a message to the DLL in question and tell it to End, I can avoid this block and move forward. I don't need the stream to continue recording in the background if I can make it work without it. I just need it to tell it to stop before the app is in the background so it doesn't crash.

    I really do appreciate you taking the time to answer my questions James but I really need some sort of direction and a little more understanding of what are my options in this matter so I can determine how to proceed on this application. I would like to know as well if the implementation I described is possible with a Metro app and more or less that I am just waiting on this documentation to be released (ie. making the dll run as a background process). And if you can let me know my question above about launching a bit of code before the app goes into the background, that'd be great. Let me know your thoughts on what should be my next steps and thanks again for your feedback.

    Thanks,

    Matthew

     

     

    Friday, July 27, 2012 10:14 PM
  • Hello Matthew,

    This link should get you started:

    http://msdn.microsoft.com/en-us/library/windows/apps/hh464925.aspx

    -James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Monday, July 30, 2012 8:52 PM
    Moderator
  • Okay Matthew,

    I've been working with the audio architect to understand all of our options for working with audio in the background. If you are writing a communications app such as VO/IP, etc. we do have low level hooks to allow you to continue to run in the background. Since background tasks can drain the battery rather quickly I would recommend that you avoid doing this if possible.

    Here is a link to a sample that should show you all you need to do:

    http://code.msdn.microsoft.com/windowsapps/Audio-hardware-offload-280dc923

    Thanks,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Monday, July 30, 2012 9:11 PM
    Moderator
  • Hey James,

    Thanks for taking the time to look into this for me and check in with the local dev team. Much appreciated! I actually an hour after leaving my last post that day was able to come up with a workaround. My Metro application basically opens up a stream from a recording input such as a microphone and analyzing the byte stream as it comes in. Without saying too much on what the app is, I need to do a level of spectrum analysis on the audio samples coming into the app in real-time.

    As a reference to how the library is setup that handles this processing, its a standard C++ DLL that doesn't have the option selected in the Project Properties that mentions something along the lines... "Use this application as a metro library". I have a question about that one but I'll save it till later. To fill you in on what is my workaround is for the time being in the DLL is actually quite simple and kind of made me have one of those moments I wished I thought of it earlier.... okay so in the example on "How To Record A Stream Using WASAPI" in the link I posted back to you above, it has this to pass the data from the recording to a client-side defined AudioSink...

    // Copy the available capture data to the audio sink.
    hr = pMySink->CopyData(pData, numFramesAvailable, &bDone);
    EXIT_ON_ERROR(hr)

    When the application is suspended into the background, the streams in question being accessed are being blocked causing the nasty exception to flow back to my C# Metro app giving me a AccessViolationException. In my code to rectify this, all I did is check to see if the pointer to pData was null and if so, end capture and close out the stream. This allowed it close out without causing an error and I have a special callback that fires back to the C# app telling it that the capture ended abruptly and adjusts things like IsEnabled or custom Boolean variables to handle the rest. I can then take it a step further and catch the app coming out of suspension or termination (haven't programmed this yet but pretty sure how to listen for it), know that it ended abruptly and start the process when the user resumes the app. Its not at all necessary in this app to continue recording so it ended up working alright for my needs.

    I'll take a look at some of these links you left me and get back to you if I have any questions about them. In the meantime, I have a question about using C++ DLLs with C# Metro apps and potential guideline conflictions. Excuse me if I get a little off topic. The flag in the Project Properties that asks about enabling this library for Metro Style apps, is this necessary in my case to bring this to the Marketplace and is the method that I described using the DLL with simple DLLImport/Export an okay enough route? Also, if I have a C++ DLL, how can I set the compilation of the solution to not only support x86, x64 but also WinRT (ARM) as well and maybe if there is a link to detail how to package up a C++ DLL in this case for multiple platforms.

    Thanks again for your assistance James and looking forward to your feedback, take care and enjoy the end to your week. :)

    Thanks,

    Matthew

    Friday, August 03, 2012 7:53 AM
  • Hello Matthew,

    Please post your new question in the tools forum and someone should be able to help you. However it is not clear to me what you are asking. C++ DLLs are native and must be compiled for the platforms you are targeting. I believe that the store requires x86 and ARM support to be accepted.

    -James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Monday, August 06, 2012 8:28 PM
    Moderator
  • Hey James,

    Not a problem moving the question to the right thread having to do with the setting in the project properties relating to C++ DLLs. About the one I maybe didn't explain correctly, I have been out of the loop in C++ for a little and didn't know if the new VS 2012 had a way to setup compiling the DLL for all targeted platforms in one go or a way that the Metro solution is aware of the C++ project and automatically compiles the different versions when publishing the build to ARM or x86. I didn't expect to find something like this but thought I'd ask anyway just in case something was present to make this a little quicker or easier when getting the final builds ready for publishing. I haven't taken much time to review how to package up apps/games for the marketplace so I'll do a little research and if I run into any issues, I'll create a new thread about it.

    I will be spending some time today checking out the your last post about Audio Offloading. This app will not need to continue to record if it is not in focus so I can disable it once the app is suspended. Do you feel that my workaround where I check to see if pData is NULL is sufficient? pData is simply the pointer to the buffer currently available coming from the recording input described in the "Recording A Stream Using WASAPI" on msdn. I had seen a BSOD the other day when I thought the app was recording and my PC entered sleep mode but I am having problems trying to reproduce the issue so I can't yet determine if my app was the cause. I'll try looking at the sample you posted and see if it has what I need to avoid relying on the workaround and get back to you if I have any further questions and if you could let me know your thoughts on using that workaround, that'd be great.

    Oh and one last thing I wanted to get your input on James is something I posted above. What do you think about me using the DLL with the standard DLLImport/Export method? Is there a better or more recommended way when creating C# based Metro apps or is that totally okay? With all these changes with how apps are work and being handled on the OS with Metro, I didn't know if there was anything else I should be looking out for with how my solution is setup and doing the interop.

    Thanks again for your input James

    Matthew

    Wednesday, August 08, 2012 11:33 PM
  • Q. Do you feel that my workaround where I check to see if pData is NULL is sufficient?

    A. Probably but you should have hooks into your library that can allow the owning application to shut it down properly when the app is suspended.

    Q. What do you think about me using the DLL with the standard DLLImport/Export method?

    A. I honestly can't think of a good reason to use the DLL Import methods. If you want your C++ Cx component to be available to C# applications you should make sure to decorate your C++ Cx app properly to be called from C# as a WinRT component.

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Friday, August 10, 2012 1:35 AM
    Moderator