c# - 调用 Dispose() 后程序挂起

标签 c# multithreading sockets webcam dispose

我正在使用 C# 开发一个 iOS 项目。该程序从连接的网络摄像头捕获图像,并通过套接字将其发送到 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();
}

在 Camera 类中这样定义:

public event EventHandler<CameraEventArgs> OnImageCaptured;

并触发:

OnImageCaptured.Invoke(this, new CameraEventArgs(bitmap, fps));

所以这个功能 - 我相信 - 在一个单独的威胁中运行,因为当图像进入时 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();
    }

}

客户端断开连接,调用 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");
}

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

非常感谢任何帮助/提示。

最佳答案

这叫做死锁,典型的线程问题。我没有看到您在代码片段中的任何地方显式调用 UI 线程,因此死锁可能位于相机固件本身。核心问题是您试图关闭相机它的回调仍在执行,没有很多代码对此有弹性。在回调完成之前,Release() 调用无法完成。但是在 Release() 调用完成之前回调无法完成。死锁城。

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

关于c# - 调用 Dispose() 后程序挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10407439/

相关文章:

java - Neo4j 中锁释放导致死锁

c# - 在 C# 中使用 N 个线程处理队列的简单方法?

python - 属性错误 : module 'socketserver' has no attribute 'ForkingMixIn'

c# - 如何在 UML 中表示索引或参数化属性?

c# - 加载嵌入式程序集

c# - 值类型存储在 (C#) 泛型集合中的什么位置

c# - 错误 CS0030 : Cannot convert type 'Simple.Amazon.ECS.ImageSet[]' to 'Simple.Amazon.ECS.ImageSet' in Amazon Web Service

c# - .Net 中的负载测试应该遵循哪种方式?

c++ - 包括通过套接字监听的线程中断

java - 对于socket来说,有没有比netty更好的框架呢?