I'm working on an iOS project with C#. The program captures images from a connected webcam and sends it via Socket to the iPhone/iPad. This all works fine and I can successfully get my stream showing up on the device.
But when the client disconnects, the webcam has to get turned off and in this function, the program just hangs up. No error messages and no exception calls...just hangs! I believe it's a problem with multiple threads but unfortunately I'm not as experienced in C# to find a solution. I hope someone here can bring me on the right track...
Code:
onImageCaptured function:
public void OnImageCaptured(Touchless.Vision.Contracts.IFrameSource frameSource, Touchless.Vision.Contracts.Frame frame, double fps)
{
_latestFrame = frame.Image;
Console.WriteLine("OnImageCaptured");
if (isConnected)
{
Console.WriteLine("OnImageCaptured - isConnected");
byteArray = new byte[0];
MemoryStream stream = new MemoryStream();
_latestFrame.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
stream.Close();
byteArray = stream.ToArray();
if (byteArray.Length > 0)
{
string eof = "<EOF>";
byte[] eofByte = Encoding.ASCII.GetBytes(eof);
Console.WriteLine("OnImageCaptured - sendStream");
this.onDataSend(byteArray);
this.onDataSend(eofByte);
stream.Flush();
}
System.Diagnostics.Debugger.Log(0, "1", "\nByte Array Length: " + byteArray.Length.ToString());
}
pictureBoxDisplay.Invalidate();
}
Defined like this in Camera Class:
public event EventHandler<CameraEventArgs> OnImageCaptured;
And triggered:
OnImageCaptured.Invoke(this, new CameraEventArgs(bitmap, fps));
So this function - what i believe - runs in a separate threat since the UI is not blocked when the images are coming in.
So next the client disconnection is handled in this function:
public void onDataSend(byte[] data)
{
clientReady = false;
try
{
socketWorker.Send(data);
}
catch (SocketException se)
{
isConnected = false;
Console.WriteLine("Error: Data Write - SocketException");
Console.WriteLine(se.ErrorCode.ToString());
thrashOldCamera() // THIS FUNCTION HANGS THE PROGRAM !!
onDisconnectServer();
// onDisconnectServer();
}
catch (ObjectDisposedException)
{
isConnected = false;
Console.WriteLine("Error: Data Write - ObjectDisposedException");
// onDisconnectServer();
}
}
Client disconnects, thrashOldCamera()
is called. Works fine so far! Now:
private void thrashOldCamera()
{
Console.WriteLine("TrashOldCamera");
// Trash the old camera
if (_frameSource != null)
{
try
{
_frameSource.NewFrame -= OnImageCaptured;
Console.WriteLine("TrashOldCamera - 1");
_frameSource.Camera.Dispose(); // HERE IT HANGS. IT NEVER GOES PAST HERE !!!
Console.WriteLine("TrashOldCamera - 2");
setFrameSource(null);
Console.WriteLine("TrashOldCamera - 3");
pictureBoxDisplay.Paint -= new PaintEventHandler(drawLatestImage);
}
catch (Exception ex)
{
Console.WriteLine("End Trash Camera Ex: " + ex);
}
}
Console.WriteLine("End Trash Camera");
}
The program hangs at _frameSource.Camera.Dispose();
. As stated above, there's no error or exception.
It may be a problem that onDataReceive()
gets called within the onImageCapture
function().
I also added a button to the form that triggers thrashOldCamera()
and this works perfectly.
Any help/hints are truly appreciated.
This is called deadlock, a typical threading problem. I don't see you explicitly invoke to the UI thread anywhere in the snippet so the deadlock is possibly located in the camera firmware itself. The core issue is that you are trying to close the camera while its callback is still executing, there's not a lot of code that's resilient to that. The Release() call can't complete until the callback completes. But the callback can't complete until the Release() call completes. Deadlock city.
You'll need to restructure your code so this cannot happen. Delaying releasing the camera is key, best done on the same thread that opened the camera. You'll probably solve it by releasing it in the FormClosed event for example. Or not releasing it at all and leaving it up to Windows to automatically close handles.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With