调用Dispose()后程序挂起

Pas*_*cal 5 c# sockets webcam multithreading dispose

我正在使用C#开发iOS项目.该程序从连接的网络摄像头捕获图像,并通过Socket发送到iPhone/iPad.这一切都很好,我可以成功地让我的流出现在设备上.

但是当客户端断开连接时,网络摄像头必须关闭,在此功能中,程序才会挂断.没有错误消息和没有异常调用......只是挂起!我相信这是多线程的问题但不幸的是我没有在C#中找到解决方案的经验.我希望有人能带我走上正轨......

代码:
onImageCaptured函数:

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();
}
Run Code Online (Sandbox Code Playgroud)

在Camera Class中定义如下:

public event EventHandler<CameraEventArgs> OnImageCaptured;
Run Code Online (Sandbox Code Playgroud)

并触发:

OnImageCaptured.Invoke(this, new CameraEventArgs(bitmap, fps));
Run Code Online (Sandbox Code Playgroud)

所以这个功能 - 我相信 - 在单独的威胁中运行,因为在图像进入时UI不会被阻止.

接下来,在此函数中处理客户端断开连接:

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();
    }

}
Run Code Online (Sandbox Code Playgroud)

客户端断开连接,thrashOldCamera()被调用.到目前为止工作正常!现在:

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");
}
Run Code Online (Sandbox Code Playgroud)

程序挂起_frameSource.Camera.Dispose();.如上所述,没有错误或例外.它可能是onDataReceive()onImageCapture函数()中调用的问题.我还在触发的表单中添加了一个按钮thrashOldCamera(),这非常有效.

任何帮助/提示都非常感谢.

Han*_*ant 9

这称为死锁,这是典型的线程问题.我没有看到您在代码段中的任何位置显式调用UI线程,因此死锁可能位于相机固件本身.核心问题是你回调仍在执行试图关闭相机,没有很多代码可以恢复它.在回调完成之前,Release()调用无法完成.但是,在Release()调用完成之前,回调无​​法完成.死锁城市.

您需要重新构建代码,以免发生这种情况.延迟释放相机是关键,最好在打开相机的同一个线程上完成.您可能会通过在FormClosed事件中释放它来解决它.或者根本不释放它并将其留在Windows上以自动关闭句柄.