How do you stop SoundEffect from crashing XNA windows games when they are closed? - c#

I am creating a game for windows in xna using Visual C# Express. In the game, there are six SoundEffect objects which regularly have their Play() methods called. The problem is that sometimes when the game is closed it crashes. It appears to happen whenever the window is closed while a soundeffect is playing. This is the message which pops up in Visual C#:
AccessViolationException was unhandled
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
There isn't any source available in visual studio to debug and when the "get general help for this exception" is clicked, a blank page pops up..
The code used looks a lot like the MSDN example. This looks like a problem that exists somewhere in the underlying framework somewhere, not my code. But of course I don't know for sure. This has happened many times.
http://msdn.microsoft.com/en-us/library/bb195053.aspx
Here are the complete exception details:
System.AccessViolationException was unhandled
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=Microsoft.Xna.Framework
StackTrace:
at Microsoft.Xna.Framework.Audio.AudioCallbackDispatcher.IsEventRegistered(EventType type)
at Microsoft.Xna.Framework.Audio.AudioCallbackDispatcher.UnregisterEvent(EventType type)
at Microsoft.Xna.Framework.Audio.KernelMicrophone.ShutdownCaptureEngine()
at Microsoft.Xna.Framework.Audio.MicrophoneUnsafeNativeMethods.ShutdownCaptureEngine()
at Microsoft.Xna.Framework.Audio.AudioRendererShutdownHandler.AppExitingEventHandler(Object sender, EventArgs args)
InnerException:
(I also have music playing via MediaPlayer, but I don't think it's related.)
EDIT: I seem to have found something which works, but it's kind of hackish and really shouldn't be necessary. I'm still open to any more elegant solutions.
Call this line in Game1.UnloadContent(). It will make sure (if your sound effects are all shorter than 3 seconds) that no sound is playing when the program actually closes.
System.Threading.Thread.Sleep(3000);

Make the SoundEffect object a class member and call the SoundEffect's Dispose() method on class deconstruction:
class MyClass
{
~MyClass()
{
effect.Dispose();
}
SoundEffect effect;
}
This should let the SoundEffect object clean itself up when you close the game. You can read about objects that are Disposable here: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

Can you make MyClass implement IDisposable and dispose of the SoundEffect in that method?

I think it's pretty safe to say that this is a bug in the framework. Because it's in the audio code, perhaps the framework is not handling something it's getting from a driver correctly. It's hard to say for sure.
Suffice to say that an AccessViolationException coming out of the framework is not "normal". It's almost certainly not your fault.
The function IsEventRegistered that the exception occurs in is an unsafe function. So it's likely that function is doing exactly what the exception says: it is accessing an invalid memory address.
The exception is coming from the shutdown code for audio capture (microphone), so are you doing anything with the microphone in your code? You could possibly experiment with using/not using the microphone and see what happens.
Also: does this happen when you run without the debugger attached? (Ctrl+F5)
As for fixing the problem: Your solution is not a bad work-around.
If you cannot afford to wait the three seconds, and you want to get your hands dirty and write some very questionable (semi-unportable, not-necessaraly-forward-compatible) code: You could use reflection to access the private properties of the audio system. Find the list of SoundEffectInstance objects that are created internally whenever you call SoundEffect.Play, and then stop those instances before you shutdown.
Or you could do effectively the same thing by never calling Play, but instead calling CreateInstance and managing fire-and-forget sound effects on your own. The downside is that this requires writing an awful lot of code!

I had the same problem and I did nulls for my sound collections in class finalizer(destructor). Works for me.
public class Audio
{
private ContentManager content;
public List<SoundEffectInstance> SoundInstance { get; private set; }
public AudioEmitter Emitter { get; set; }
public AudioListener Listener { get; set; }
public List<SoundEffect> Sound { get; set; }
public Audio(ContentManager content)
{
this.content = content;
Emitter = new AudioEmitter();
Listener = new AudioListener();
Sound = new List<SoundEffect>();
SoundInstance = new List<SoundEffectInstance>();
}
//set to null your sound instances and effects :D
~Audio()
{
Sound = null;
SoundInstance = null;
}
...

Related

Why I'm receiving Access Violation Exception when try to dispose VideoView in LibVLCSharp

I'm using Stylet as MVVM framework and LibVLCSharp.WPF 3.6.5 + VideoLAN.LibVLC.Windows 3.0.16 in my project for streaming camera rtsp streams.
VideoView is included in my VLCPLayer custom user control, and that control is exposed as a property in my view model. I don't know if this is a good thing, but in this way I managed to make some kind of custom full screen video with custom buttons.
Everything works fine until I try to close player, or better to say try to dispose VideoView.
I have something like this:
public void Dispose()
{
//these are custom events in my user control
VlcPlayer.ClosePlayer -= ClosePlayer;
VlcPlayer.RestorePlayer -= RestorePlayer;
VlcPlayer.MinimizePlayer -= MinimizePlayer;
//here I try to dispose player and VideoView
VlcPlayer.VideoView.MediaPlayer.Stop();
VlcPlayer.VideoView.MediaPlayer.Media.Dispose();
VlcPlayer.VideoView.MediaPlayer.Dispose();
//here I'm getting Access Violation Exception
VlcPlayer.VideoView.Dispose();
}
If I don't dispose VideoView it remains in memory and every time I start new stream new VideoView is added to memory, so if I opened and closed one stream and then opened the same or whatever stream, I'll have in memory 2 VideoViews instead of one. I have to release memory of unused VideoViews and players since application will be used for some kind of surveillance, so it will have lot of streams at the same time opened, and lot of VideoViews opened.
Here I found similar issue, but it was reportedly solved updating to newest version of LibVLCSharp, but my version is newer than from mentioned post and I still have similar problem.
I'd appreciate any kind of help on this issue. Thanks.

Emgu/OpenCV: Event for VideoCapture.QueryFrame() finished.

Here is the basic idea of my code:
private void CaptureCameraFrame()
{
Capture = new VideoCapture();
CameraModel.Instance.CameraViewMat = Capture.QueryFrame();
// do stuff with queried matrix here
if(noAbortCondition)
{
CaptureCameraFrame();
}
}
The method should run in a separate thread updating my GUI with the current image after processing.
Only Problem is, that I get two different kinds of error:
Attempt to read/write protected memory: This happens on the second runthrough
of the method.
I get an null-reference error using `CameraModel.Instance.CameraViewMat right after querying the frame.
The two issues seem to be connected, seems like QueryFrame() runs asynchronously from the rest of the code and isn't done when the program jumps to the next step.
Question is: How can I make sure, that querying the image from the camera is finished, and I can use the information in the matrix as well as start a new query?
In all the examples I have found this is done by using time, but I would like to start with a new frame as soon as processing on the last frame is done.
I haven't really done much in C# when it comes to threading, but what I understand in such cases one would use the asyncand awaitkeywords to make sure a method in an asynchronous method is finished. However I wasn't able to make a working implementation in this case.
You are creating VideoCapture class instance repeatedly and even not disposing of it. Create your VideoCapture instance only once and use them for your task. At the end dispose it.
public YourConstructor()
{
Capture = new VideoCapture();
}
private void CaptureCameraFrame()
{
CameraModel.Instance.CameraViewMat = Capture.QueryFrame();
// do stuff with queried matrix here
if(noAbortCondition)
{
CaptureCameraFrame();
}
}
Hopefully, it will work for you!

ObjectDisposedException: Safe handle has been closed

So this is a rather small question with a big explanation. As is noted by the title I am getting an unhandled exception telling me my Safe handle has been closed. What I'll probably have to do is edit this post a few times with more and more code to help me diagnose what the problem is.
I'm using POS for .NET to make a Service Object for my RFID and MSR device. Although my devices are the same, I have 2 different Virtual COM Port chips that communicate to those devices. One by Silicon labs, the other by FTDI. I wanted to use the plug and play features with POS for .NET so I gave it both my Hardware ID's. Because it is plug and play I have the full hardware path available to me which I can then create a SafeFileHandle using a call to PInvoke and using that SafeFileHandle I create a FileStream. The FTDI chip doesn't let me talk to the devices directly like that so I have to get the friendly name of the device then use mutex to pull out the COM port then create a SerialPort instance. That step works fine and great. As a FYI I have tried to use the Friendly name of both chips to get the COM port and the Silicon Labs one (for some strange reason) doesn't get listed using SetupAPI.GetDeviceDetails using the Ports GUID. I'm not sure on that one since in Device Manager the Silicon labs Device Class Guid is the Ports GUID.
Well since both the SerialPort and the FileStream have a Stream object I decided to use that to read and write to that port. The problem with that is if I send a RFID command to the MSR device the MSR device doesn't respond back with anything. So if I use this code int fromReader = ReaderStream.ReadByte(); my thread is blocked. It's a blocking call and requires a minimum of 1 byte to proceed. So I looked around and it appears the only solution is to use a separate thread and set a timeout. If the timeout happens then abort the thread.
Thread t = new Thread(new ThreadStart(ReadFromStream));
t.Start();
if (!t.Join(timeout))
{
t.Abort();
}
(t.Abort has been surrounded with a try/catch to no avail, since it didn't fix the problem I removed it)
ReadFromStream is Abstract method in RFID Device. Here is one of the implementations
protected override void ReadFromStream()
{
var commandLength = USN3170Constants.MIN_RESPONSE_LENGTH;
var response = new System.Collections.Generic.List<byte>(USN3170Constants.MIN_RESPONSE_LENGTH);
for (int i = 0; i <= commandLength; i++)
{
int fromReader = ReaderStream.ReadByte();
if (fromReader == -1) break; //at end of stream
response.Add((byte)fromReader);
if (response.Count > USN3170Constants.DATA_LENGTH_INDEX && response[USN3170Constants.DATA_LENGTH_INDEX] > 0)
{
commandLength = response[USN3170Constants.DATA_LENGTH_INDEX] + 3;
}
}
streamBuffer = response.ToArray();
}
(int fromReader = ReaderStream.ReadByte(); was surrounded with a try/catch. Only thing it caught was the aborted thread exception, so I took it out)
The above code is where I suspect the problem lies. The strange thing is, though, is that I have a unit test which I feel mimics rather well the Microsoft Test App.
(FYI QUADPORT is the FTDI chipset)
PosExplorer posExplorer;
DeviceCollection smartCardRWs;
[Test]
public void TestQuadPortOpen()
{
posExplorer = new PosExplorer();
smartCardRWs = posExplorer.GetDevices(DeviceType.SmartCardRW, DeviceCompatibilities.CompatibilityLevel1);
//if using quadport one item is the MSR and the other is the RFID
//because of that one of them will fail. Currently the first Device in the collection is the the RFID, and the second is MSR
Assert.GreaterOrEqual(smartCardRWs.Count, 2);
//Hardware Id: QUADPORT\QUAD_SERIAL_INTERFACE
foreach(DeviceInfo item in smartCardRWs)
{
Assert.AreEqual("QUADPORT\\QUAD_SERIAL_INTERFACE", item.HardwareId);
}
SmartCardRW rfidDevice = (SmartCardRW)posExplorer.CreateInstance(smartCardRWs[0]);
SmartCardRW msrDevice = (SmartCardRW)posExplorer.CreateInstance(smartCardRWs[1]);
rfidDevice.Open();
Assert.AreNotEqual(ControlState.Closed, rfidDevice.State);
rfidDevice.Close();
try
{
msrDevice.Open();
Assert.Fail("MSR Device is not a RFID Device");
}
catch
{
Assert.AreEqual(ControlState.Closed, msrDevice.State);
}
rfidDevice = null;
msrDevice = null;
}
When I run that test I do not get the SafeFileHandle exception. In fact the test passes.
So I am at a loss as to how to track down this bug. Since I'll be using this Service Object in a different program that I am also creating I'll probably end up using this code from this test in that program. However I feel that the Microsoft Test App is more or less the "Golden Standard". Is it really... probably not. But it does work good for my purposes, SO I feel it is a problem with my code and not theirs.
Any tricks on how I can narrow this down? FYI I've tried using the debugger but walking the Open Code the error does not occur. I also walked the Update Status Timer and it also does not throw the error. Once I hit continue then I'll get the exception. I turned of Just My Code and Loaded Symbols and it tells me "Source Information is missing from teh debug information for this module"
This problem (and in particular the reference to a SerialPort instance) sounds suspiciously like the problem documented at http://connect.microsoft.com/VisualStudio/feedback/details/140018/serialport-crashes-after-disconnect-of-usb-com-port.
As I understand it, in the case of a non-permanent SerialPort (like one associated with a USB device, for example) when the port "goes away" unexpectedly the underlying Stream associated with it gets disposed. If there is an active read or write operation on the port at the time a subsequent call to SerialPort.Close can lead to the exception you mention, however the exception is occurring in Microsoft's code running on a different thread and cannot be caught from within your code. (It will still be seen by any "last chance" exception handler you have bound to the UnhandledException event on the AppDomain.)
There seem to be two basic workaround styles in the linked document. In both instances, after opening the port you store a reference to the BaseStream instance for the open port. One workaround then suppresses garbage collection on that base stream. The other explicitly calls Close on the base stream, capturing any exceptions thrown during that operation, before calling Close on the SerialPort.
EDIT: For what it's worth, under the .NET framework V4.5, it appears that none of the documented workarounds on the Microsoft Connect site fully resolve the problem although they may be reducing the frequency with which it occurs. :-(
I had the same error when I used a thread to read from a SerialPort. Calling Interrupt on the thread occasionally caused the uncatchable ObjectDisposedException. After hours of debugging and carefully reading this:
https://blogs.msdn.microsoft.com/bclteam/2006/10/10/top-5-serialport-tips-kim-hamilton/
I realized that the problem is just this:
NET 2.0 (and above) isn’t letting you get away with some things, such as attempting to cancel a SerialPort read by interrupting the thread accessing the SerialPort.
So before you call Thread.Interrupt() you have to close the COM... This will cause a catchable exception on the ReadByte operation.
Or you may use the ReadTimeout property on the SerialPort to avoid using a thread just to have a timeout.
I would like to post my case in which I had a similar issue trying to read from a serial port (virtual com driven by a Moxa RS232 to ethernet).
Since I did have no chance to catch the ObjectDisposedException, the only solution was to increase the ReadTimeout property which was originally set to -1 (continuous reading).
Setting the ReadTimeout to 100 millis solved this issue in my case.
EDIT
It is not the definitive solution: it can happen that if you close the application during a read attempt you can get the same uncatchable exception.
My final solution is to kill the process of the application directly in the FormClosing event :
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
Process p = Process.GetCurrentProcess();
p.Kill();
}
Please take a look at this:
https://github.com/jcurl/SerialPortStream
I replaced System.IO.Ports with RJPC.IO.Ports, fixed up a couple parameter differences in the initialization, and all the problems went away with this issue.

How to check if sound effect is playing (Looping a BG Song)

Here is the setup I am rolling at the moment. Given this, how can I tell when the _BGMusic SoundEfect is over? I am running a game loop that cycles a few times a second and I ultimately want to loop this song.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
SoundEffect _BGMUSIC;
public Page1() {
...
LoadSound("sfx/piano.wav", out _BGMUSIC);
...
}
private void LoadSound(String SoundFilePath, out SoundEffect Sound) {
// For error checking, assume we'll fail to load the file.
Sound = null;
try {
// Holds informations about a file stream.
StreamResourceInfo SoundFileInfo =
App.GetResourceStream(new Uri(SoundFilePath, UriKind.Relative));
// Create the SoundEffect from the Stream
Sound = SoundEffect.FromStream(SoundFileInfo.Stream);
FrameworkDispatcher.Update();
} catch (NullReferenceException) {
// Display an error message
MessageBox.Show("Couldn't load sound " + SoundFilePath);
}
}
From this code it looks like you have just stored the sound in Sound but you don't show where you implement the Sound.Play() method. While there isn't a Sound.IsPlaying boolean which would probably solve your problem, there is a Sound.Duration property which you may use to solve your problem, especially if you couple that with a Timer (which can be used in tandem to set off a flag to show whether or not the sound is playing.
Also something I have never used but just found is the Sound.IsDisposed property. I would definitely look into this as well because it may be exactly for what you are looking.
Alright so the answer to this question is actually very simple and outlined in Microsoft's MSDN page very nicely (for once).
To implement it with what I have up above currently you need to do the following.
Create a global SoundEffectInstance
SoundEffectInstance _BGMUSICINSTANCE;
In my example I initialize the SoundEffect in my main method so underneath it I want to initialize the SoundEffectInstance.
_BGMUSICINSTANCE = _BGMUSIC.CreateInstance();
Now that the instance is loaded and ready we can set its loop property to true. You can do this also in the main method or wherever you want. It's a global
_BGMUSICINSTANCE.IsLooped = true;
Finally play the song
_BGMUSICINSTANCE.Play();
Reference page
http://msdn.microsoft.com/en-us/library/dd940203(v=xnagamestudio.31).aspx

c# console application sub windows

I'd like for a single console application to spawn other console windows and output to different ones at different times inside of a C# console application. Preferably within one console application, I spawn some other consoles, write to them, and close them during the finally block of the original console application.
What's the ideal way to do this in C#?
I don't believe you can do this with a regular console application. The closest you could come would be to create a your own form in WinForms/WPF which behaved in roughly the same was as a normal console window.
I suppose you could spawn extra processes which each had their own console, and write to them via network connections or named pipes etc... it would be pretty ugly though.
You can do this with Auto/Manual EventWaitHandles in C# combined with countless other techniques. However, you should probably step back and see what you are trying to accomplish and see if a winform app would be a better fit. Maybe post more details and ask for ideas.
A single process can only ever have one true Standard In, Error and Out.
You can fake different ones, especially in .Net because after all they are presented as managed streams which would be fine at the push/pull and of the pipe. The problem is the output/input end i.e. the bit you might be piping to a file, or where you are requesting user input. These simply won't play ball since the OS supplies no multiplexing method itself.
Using simple means at best you could do something that sent output to multiple different windows which looked much like a console window.
With much complexity you would handle reading from them too. In essence you are writing a window which pretends to be a console, and getting it reasonably close to all the little intricacies of console windows is (increasingly) hard.
It would be simple to have (say) a fake console per thread by creating a class like so. I only bother with Out, In and Err follow easily from this.
public class MultiplexByThreadConsole : IDisposable
{
private readonly TextWriter originalOut;
private readonly TextWriter myOut = new IndividualMultiplex();
public MultiplexByThreadConsole()
{
this.originalOut = Console.Out;
Console.SetOut(this.myOut);
}
public void Dispose()
{
Console.SetOut(this.originalOut);
}
private class IndividualMultiplex : TextWriter
{
[ThreadStatic]
private readonly TextWriter actual;
// override all the required functions and any
// others you want to wrap
public override void Write(char c)
{
if (actual == null)
{
actual = MakeWhateverYouReallyWantToOutputTo();
}
actual.Write(c);
}
}
}
Then somewhere in Main (or wherever) do:
using(new MultiplexByThreadConsole())
{
// off you go all threads during this get their own faked console.
}
You would likely keep the In/Out/Err all pointing to some common objects writers/reader which was itself the fake console.
This is however pretty nasty. I would say that, if you truly want to launch things that look like separate consoles then you should actually do that and launch a new process for each one with a glue back end to manage them (somewhat similar to the concept of Chrome's back end processes per tab).

Categories