Windows phone crash device.Sensors.ni.dll - c#

I am experiencing some crashes on my app (somewhat similar to a compass app). The windows crash report is telling me this:
frame 0:
Microsoft.Devices.Sensors.ni.dll; Microsoft.Devices.Sensors.Accelerometer.Start; 0x0000006c
frame 1:
PivotApp1.ni.DLL; PivotApp1.MainPage+_start_d__0.MoveNext; 0x000001d4
frame 2:
mscorlib.ni.dll; System.Runtime.CompilerServices.AsyncMethodBuilderCore._ThrowAsync_b__3; 0x00000036
I am unable to understand what this exactly means here. Based on what I get from it, it is probably because of the accelerometer.
This is my current code and It seems like the error is generated from somewhere in here :
private async void start()
{
//Check for the user agreement in use his position. If not, method returns.
if ((bool)IsolatedStorageSettings.ApplicationSettings["LocationConsent"] != true)
{
// The user has opted out of Location.
MessageBox.Show(AppResources.main_cantuse);
Application.Current.Terminate();
}
else
{
//KOMPASS
if (compass == null)
{
// Instantiate the compass.
compass = new Compass();
// Specify the desired time between updates. The sensor accepts
// intervals in multiples of 20 ms.
compass.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
compass.CurrentValueChanged +=
new EventHandler<SensorReadingEventArgs<CompassReading>>(compass_CurrentValueChanged);
compass.Calibrate +=
new EventHandler<CalibrationEventArgs>(compass_Calibrate);
}
try
{
compass.Start();
timer.Start();
accelerometer = new Accelerometer();
accelerometer.CurrentValueChanged +=
new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(accelerometer_CurrentValueChanged);
accelerometer.Start();
}
catch (InvalidOperationException)
{
MessageBox.Show(AppResources.main_unabletostart);
}
I would like to ask, Do I have to check if the accelerometer is ready (or null check or something else) ?
Any help or guidance here is appreciated.

Those crashes are probably from devices that do not have a compass (yes, there are devices like this out there).
You should check for the compass with Compass.IsSupported and only use it when it returns true.

Related

NAudio hanging and crashing when default device is changed

I've been stuck on this all day, so I'm going to post everything I've been able to find today that might be useful to helping me, it will be a long post. I'm having 2 issues that I believe are related to the same problem. First, let me explain what I am doing. I have 3 Winforms combo boxes that are bound to lists of all of the devices found by MMDeviceEnumerator. Two output device boxes, one input device. I am using the MMDeviceEnumerator to register a callback for whenever the devices are changed, removed, or a default device is set. The callback fires an event that then invokes a delegate to the form thread to re-enumerate the devices into combo boxes. It looks like this:
public void OnDefaultDeviceChanged(DataFlow dataFlow, Role deviceRole, string defaultDeviceId)
{
Devices.OnDevicesUpdated();
}
//The handler called by this event:
private void UpdateDeviceSelectors(object? sender = null, EventArgs? e = null)
{
Invoke(delegate ()
{
int primaryIndex = Devices.PrimaryOutput + 1, secondaryIndex = Devices.SecondaryOutput + 2, microphoneIndex = Devices.Microphone + 1;
Devices.Refresh();
try
{
SecondaryOutputComboBox.SelectedIndex = secondaryIndex;
PrimaryOutputComboBox.SelectedIndex = primaryIndex;
MicrophoneSelectComboBox.SelectedIndex = microphoneIndex;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
});
}
Now for the two issues I have. The first one involves a semi-random crash that leads back to NAudio.Wasapi.dll, where a System.ExecutionEngineException is thrown. It is kind of easy to reproduce. All I do is change the values of the combo boxes, switch the default devices around, and it will randomly crash.
The second issue occurs when another part of my code is involved. I have a microphone injector, which redirects a WaveInEvent that records a selected input device to a WaveOutEvent, like a loopback. Here is the relevant code for this:
public void Start()
{
if (Soundboard.Devices.SecondaryOutput == -2) return;
micStream = new WaveInEvent();
micStream.BufferMilliseconds = 50;
micStream.WaveFormat = new WaveFormat(44100, WaveIn.GetCapabilities(Soundboard.Devices.Microphone).Channels);
micStream.DeviceNumber = Soundboard.Devices.Microphone;
WaveInProvider waveIn = new(micStream);
var volumeSampleProvider = new VolumeSampleProvider(waveIn.ToSampleProvider());
volumeSampleProvider.Volume = 1 + Settings.Default.MicrophoneGain;
virtualCable = new WaveOutEvent();
virtualCable.DesiredLatency = 150;
virtualCable.DeviceNumber = Soundboard.Devices.SecondaryOutput;
virtualCable.Init(volumeSampleProvider);
micStream.StartRecording();
virtualCable.Play();
}
public void Stop()
{
try
{
if (micStream != null && virtualCable != null)
{
micStream.Dispose();
micStream = null;
virtualCable.Dispose();
virtualCable = null;
}
}
catch
{
micStream = null;
virtualCable = null;
}
}
In the delegate mentioned earlier, I am calling the Stop method of the Mic Injector and then the Start method to refresh the WaveIn and WaveOut devices to use the current device numbers so users do not see a device selected when a different device is being used. When this happens, the program, rather than crashing instantly and inconsistently, always hangs and has to be killed from the task manager. I am certain these 2 problems are related to the same root cause, but I have no idea what that root cause may be. Switching to Wasapi, DirectSound, or ASIO won't work because they lack certain functionalities I need, so I would really like to get this working still using Wave streams.
I've tried to find different ways to detect the device changes, assuming it is an issue deep inside NAudio, but I just can't find anything else. For the second problem specifically, I have moved the calls to the Mic Injector around thinking it may be a threading issue or something, but it didn't work or change the behavior.

Start async task without waiting for it to finish, but check for completion

I've been searching for a correct answer very hard, and all I find is either too complicated or not doing what i'm looking for.
The case is simple:
I want to start a task asynchronously every now and then. The same task always. There's no defined interval of time to start it (suppose it's random).
The task takes no arguments and doesn't return anything.
I don't want to wait for it to finish. It can't interfere with the rest of the program.
I want to check if it finished before firing it again. Don't want the same task running many times simultaneously. Just one each time.
I don't want to use timers or global variables like semaphors or something. Just a plain and clean solution for a very simple problem.
I've tried background workers, but the tasks overlap as I can't find a reliable way to check for completion. I've tried running tasks but they can't be restarted. I've tried with async/await but I don't want to wait for completion.
EDIT:
I'll provide more information. This application is for a facial recognition SW. I have to handle 3 cameras and I'm using EmguCV. Each camera suscribes to an ImageGrabbed Event called "ProcessFrame", so I have ProcessFrame1, ProcessFrame2 and ProcessFrame3. The Events are fired up at nearly the fps of each camera, given so, the frequency is very high. In each Event I take a capture and show it up in an ImageBox (Emgu's pictureBox). Every 5 captures I check if I have at least one capture of each camera, in which case, instead of showing it in the imagebox I perform a facial recognition on each image. This is the task I want to perform in a separate task, to avoid stopping the live video for each camera.
Right now I'm trying with a semaphore, as suggested by some of you, although I had some trouble on setting the chance to perform a DetectFace() in the three Events, so i just left one up.
Here is a snippet:
public Form1()
{
InitializeComponent();
//Instantiate each camera
//Subscribe to ProcessFrame1, ProcessFrame2 and ProcessFrame3
}
private void ProcessFrame1(object sender, EventArgs e)
{
if (captures[0] != null) //captures[0] is the handle for the camera 1
{
Mat snapshot = new Mat();
captures[0].Retrieve(snapshot);
if (snapshot != null)
{
frameCounter1++;
if (frameCounter1 > 5 && taskCompleted)
{
frameCounter1 = 0;
if (images[0] == null)
{
Image<Bgr, Byte> img = snapshot.ToImage<Bgr, Byte>();
images[0] = img.ToBitmap();
}
if (images[0] != null && images[1] != null && images[2] != null)
{
Thread hilo = new Thread(() => DetectFace());
hilo.IsBackground = true;
hilo.Start();
}
return;
}
else
imageBox1.Image = snapshot;
}
}
}
private void ProcessFrame2(object sender, EventArgs e)
{
if (captures[1] != null) //captures[1] is the handle for the camera 2
{
Mat snapshot = new Mat();
captures[1].Retrieve(snapshot);
if (snapshot != null)
{
frameCounter2++;
if (frameCounter2 > 5 && taskCompleted)
{
frameCounter2 = 0;
if (images[1] == null)
{
Image<Bgr, Byte> img = snapshot.ToImage<Bgr, Byte>();
images[1] = img.ToBitmap();
}
//I used to have the checking to fire up another DetectFace here
return;
}
else
imageBox2.Image = snapshot;
}
}
}
private void ProcessFrame3(object sender, EventArgs e) //Same as ProcessFrame2
private void DetectFace()
{
taskCompleted = false;
//Processing of Images
//Clear array of images
taskCompleted = true;
}
Tasks work with states so you can start your task, save a reference in a variable and check the current status of your task whenever you want.
Here is the .NET documentation to read up on the different states of a task:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.status?view=netframework-4.7.2
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskstatus?view=netframework-4.7.2
sadly I'm not able to give you a code example at the moment but I hope the idea helps.
I finally achieved the threadsafe solution using BlockingCollection. Thanks to #Damien_The_Unbeliever for pointing out to the right direction.
I think it's been an important lesson when working with images in a multithreading environment. I've learned that images are very vulnerable when sharing them in different threads.
As I posted in the question, here I have to take snapshots from X different webcams, show them in X different imageBoxes and, as fast as I can (without interrupting the fps of the shown video too much), perform an image processing instead of showing the frame in the imageBox. Using a BlockingCollection I don't need to stablish a frequency for processing the frames as I did before (every 5 frames). Now I can show the frame of each camera as long as I already have a frame from that camera added to the BlockingCollection.
Another important detail to note is, in the .NET documentation for BlockingCollection it says that by default it implements a FIFO as it's a ConcurrentQueue in the lower layer, but I think this isn't true, as I have had to define it myself when instantiating:
BlockingCollection<Tuple<int, Image>> tupleCollection = new BlockingCollection<Tuple<int, Image>>(new ConcurrentQueue<Tuple<int, Image>>(), X);
As the Take() method can't target the desired element in the collection, I had to use a tuple to know to which camera the frame belonged, and to take the frames in order I had to define the ConcurrentQueue.
So basically the pseudocode is this:
void Main()
{
//Instantiate cameras
//Subscribe to the ImageGrabbed events of each (producers)
// A simple blocking consumer with no cancellation.
Task.Run(() => DetectFace());
}
producer1(sender, e)
{
//Get snapshot
...
if (!tupleCollection.Any(x => x.Item1 == 1))
{
tupleCollection.Add(new Tuple<int, Image>(1, snapshot));
}
else
imageBox1.Image = snapshot;
}
producer2(sender, e)
{
//Get snapshot
...
if (!tupleCollection.Any(x => x.Item1 == 2))
{
tupleCollection.Add(new Tuple<int, Image>(2, snapshot));
}
else
imageBox2.Image = snapshot;
}
...
producerX(sender, e)
{
//Get snapshot
...
if (!tupleCollection.Any(x => x.Item1 == X))
{
tupleCollection.Add(new Tuple<int, Image>(X, snapshot));
}
else
imageBoxX.Image = snapshot;
}
private void DetectFace()
{
while (true)
{
Tuple<int, Image> data = null;
try
{
data = tupleCollection.Take();
}
catch (InvalidOperationException) { }
if (data != null)
{
//image processing
}
}
}
Most examples I have found use the condition IsCompletedAdded and IsCompleted to stop adding and consuming, but I needed it to be running forever, so the while(true) statement.
I have been running this code 24/7 within the last week, no racing faults by now, and the CPU processor is very limited, so I'm very satisfied with this solution and I think it's the right one.

axWindowsMediaPlayer: Black Screen on looping

I have created a Windows Form Application having axWindowsMediaPlayer control. I haven't created a playlist on it, but I have stored my .mp4 files at a particular location. I pass the path to my next video at Media Ended state. For the first time, the player receives the correct path and play. But for the second video, I can only see a black screen although the player is receiving the correct path to play.
Here is my code for Media Ended State:
private void axWindowsMediaPlayer_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if(e.newState == 8)
{
//Getting jumpTo of selected page
var selectedElementJumpToValue = MainContentAreaBl.GetSelectedElementValue(_currentId, "jumpTo");
if (selectedElementJumpToValue != null)
{
_currentId = selectedElementJumpToValue;
if (_currentId != "menu")
{
pagination.Text = MainContentAreaBl.GetPaginationText(_currentId);
LaunchPlayer(selectedElementJumpToValue);
}
else
{
this.Hide();
this.SendToBack();
menu.BringToFront();
}
}
}
}
private void LaunchPlayer(string id)
{
string selectedElementPageTypeValue = MainContentAreaBl.GetSelectedElementPageTypeValue(id);
var playerFile = Path.Combine(Common.ContentFolderPath, MainContentAreaBl.GetSelectedElementDataPathValue(id));
if (selectedElementPageTypeValue == "video")
{
InitialiseMediaPlayer();
axShockwaveFlash.Stop();
axShockwaveFlash.Visible = false;
if (File.Exists(playerFile))
{
axWindowsMediaPlayer.URL = playerFile;
}
}
else if (selectedElementPageTypeValue == "flash")
{
InitialiseShockwaveFlash();
axWindowsMediaPlayer.close();
axWindowsMediaPlayer.Visible = false;
if (File.Exists(playerFile))
{
axShockwaveFlash.Movie = playerFile;
axShockwaveFlash.Play();
}
}
}
private void InitialiseMediaPlayer()
{
axWindowsMediaPlayer.Visible = true;
axWindowsMediaPlayer.enableContextMenu = false
axWindowsMediaPlayer.uiMode = "none";
axWindowsMediaPlayer.Dock = DockStyle.Fill;
}
When I debugged my application, I saw Media Player getting the correct path after e.newState == 10 (Ready state). What am I doing wrong?
Edit 1: I found out that after my current video enters into Media Ended state, the player is stopped from playing. Even if I write axWindowsMediaPlayer.ctlControls.play();, it doesn't affect the media player. Is this a bug from in axWindowsMediaPlayer?
I have encountered this issue before as well. The most likely cause is that you are giving the command axWindowsMediaPlayer.ctlControls.play(); while the play state is still changing ( after Media Ended, it will change to Ready state). If a command is sent to the player while the play state is changing, it won't do anything. Another possible cause of your error is that sometimes Media State 9 (transitioning) needs to be included with if(e.newState == 8) such that you have if(e.newState == 8 | e.newState==9). I have had cases where it doesn't pick up on State 8 (media ending), possibly because it happens really fast and jumps to transitioning - not completely sure of this cause but I had a player that wasn't moving to the next video in the playlist because of this happening. To solve this I did something like:
if (e.newState == 8 | e.newState== 9 | e.newState== 10)
{
if (e.newState == 8)
{ //Insert your code here
}
This would vary slightly depending on what you are trying to achieve. Another thing to watch out for is using the PlayStateChange Event to set the Video URL, this causes problems as a result of re-entry problems with WMP - see other posts for further explanation on my last comment:
here is a good one and another here. Hope this helps!

C# Continuously / uninterrupted reading data (from third party SDK)

Intro:
I am developing software that uses motion trackers to analyse human motor systems. Currently I am implementing hardware from xsens and using their SDK to receive data from their wireless sensors.
The SDK offers a COM interface with a "getData" method which you call to receive the currently available xyz axis data (simplified). If you do not call getData, you skip that "beat" so you will be missing data, there is no caching in their hardware/SDK.
Problem:
My problem is that I need to get data at a rate of at least 75Hz, preferably a bit more, but 75 would be acceptable, but I am currently quickly dropping to just 20 signals per second...
If I remove the processing bit (see the sample below) I get perfect sample rates, so I think either the dequeue is causing the enqueue to pause. Or the "heavy" CPU load is causing all threads to wait. I have no idea how to figure out what is actually causing it, the profiler (EQATEC) just shows my "GetData" method is taking longer after a while.
Question:
What is the best technique to use to accomplish this? Why would my "reading" thread be interrupted/blocked? There must be more cases where people need to read from something without being interrupted, but I have been Googleing for 2 weeks now and apparently I can't find the correct words.
Please advise.
Thanks
Simplified code sample, version 4, using a MultiMedia timer (http://www.codeproject.com/Articles/5501/The-Multimedia-Timer-for-the-NET-Framework) and a BackgroundWorker
public class Sample
{
private MultiMediaTimer _backgroundGetData;
private bool _backgroundGettingData;
private BackgroundWorker _backgroundProcessData;
private ConcurrentQueue<double> _acceleration = new ConcurrentQueue<double>();
private void StartProcess()
{
if (_backgroundGetData == null)
{
_backgroundGetData = new MultiMediaTimer {Period = 10, Resolution = 1, Mode = TimerMode.Periodic, SynchronizingObject = this};
_backgroundGetData.Tick += BackgroundGetDataOnTick;
}
_backgroundProcessData = new BackgroundWorker {WorkerReportsProgress = false, WorkerSupportsCancellation = true};
_backgroundProcessData.DoWork += BackgroundProcessDataOnDoWork;
_backgroundGetData.Start();
}
private void BackgroundProcessDataOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
double value;
if (!_acceleration.TryDequeue(out value)) value = 0;
//Do a lot of work with the values collected so far,
//this will take some time and I suspect it's the cause of the delays?
}
private void BackgroundGetDataOnTick(object sender, EventArgs eventArgs)
{
if (_backgroundGettingData) return;
_backgroundGettingData = true;
//123 represents a value I am reading from the sensors using the SDK
double value = 123;
if (value == -1)
{
Thread.Sleep(5);
continue;
}
_acceleration.Enqueue(value);
if (_acceleration.Count < 5) continue;
if (!_backgroundProcessData.IsBusy)
{
_backgroundProcessData.RunWorkerAsync();
}
_backgroundGettingData = false;
}
}
I am seeing the problem here
_backgroundProcessDataThread.Start();
while (!_backgroundProcessDataThread.IsAlive){}
_backgroundGetDataThread.Start();
while (!_backgroundGetDataThread.IsAlive) {}
Well, you can see here that you are having infinite loop here and the second thread starts only after first has finished its work. i.e. first thread is done. This is in no way an ideal model.
Sorry, I recognized the issue later.
The problem is, _backgroundGetDataThread will start only after _backgroundProcessDataThread has done its work.

Chip8 Emulator - User Input

I have been writing a chip8 Emulator -- http://en.wikipedia.org/wiki/CHIP-8
I have tested all of the opcodes as well as the graphics calculations and I am now struggling with the user input. I have the following method monitoring user input and altering the registers as needed (When using the chip8 the user input alters the corresponding memory register - E.G. hitting '0' sets the V0 register to 0.
My problem is that I have the following code fetching and calculating each opcode and its operation contained in a while loop. And while this is running my application cannot detect user input. So the ROMS start and just stay locked in place waiting on a register change or user input. It keeps getting stuck in an infinite loop, I tried to implement a global Boolean RUN, and it is not detected after the while loop is initiated. I'm assuming it is out of the scope of the loop, but from what I have read, the keyboard event triggers an interrupt that should be visible from almost anywhere, any Thoughts?
This is what calculates and parses the opcode
private void button1_Click(object sender, EventArgs e)
{
// This will become the run function
do{
for (int i = 0; i < 2; i++)
{
opc[i] = mem[mc]; // fetching the instruction from the memory array
mc++;
}
cibox.Clear(); // Just clearing Debugging text boxes in the UI
pcbox.Clear();
pc++;
pcbox.Text += pc;
cibox.Text += opc[0].ToString("X2") + "-" + opc[1].ToString("X2");
calculations(opc); // Parses the Opcode and does the corresponding operation
}while(run);
}
And this method is controlling the user input...
protected override void OnKeyDown(KeyEventArgs keyEvent) // Listens for Keyboard events! Read More: http://www.geekpedia.com/tutorial53_Getting-input-from-keyboard.html
{
keyPress = true;
//Gets the key code found at keyEvent...
MessageBox.Show("KeyCode: " + keyEvent.KeyCode.ToString());
String register = keyEvent.KeyCode.ToString();
if (register == "Escape")
{
Application.Exit();
run = false;
}
try
{
registerVal = int.Parse(register, System.Globalization.NumberStyles.HexNumber); // Second Nibble! --> Int Format
}
catch (System.ArgumentNullException e)
{
return;
}
catch (System.ArgumentException)
{
return;
}
catch (System.FormatException)
{
return;
}
catch (System.OverflowException)
{
return;
}
if (registerVal >= 208)
{
registerVal = registerVal - 208;
}
if (registerVal <= 15)
{
mem[registerVal] = (byte)registerVal;
}
display(); // Alters UI to display state of registers, etc
}
So I have now tried the Game Loop Idea, but I cannot find a way to make a method in C# that will return a key press. Maybe I am missing something here, but I cannot seem to figure it out!
I also tried another method involving running the CPU calculations in a separate thread, and this is causing a slight delay issue.
I would really like to see an example of a method in C# that returns the value of a key being pressed that I can call within the While loop!
I suggest you set up your emulator's loop like a game loop. You have one global loop which triggers updates to each module in your emulator. In the loop, you call your input (or generic "event") processor, then your opcode/hardware emulation, then your screen update.
Here's some pseudo-code.
while (True):
processInput()
updateCPU()
outputGraphics()
I don't know how the key input works in C#, if it's an asynchronous event trigger (i.e. the "OnKeyDown" method gets called outside of your loop), you can set up "OnKeyDown" to just send the key events to an intermediate event manager, then in "processInput()" you actually resolve the events and use them to update registers on the emulated CPU etc.

Categories