保持UI线程的响应能力?

时间:2016-07-22 09:53:32

标签: c# wpf

我的应用程序正在使用WPF Control显示来自网络摄像头的许多视频。

摘要代码位于

之下
public void DisPlayVideoThreadProc()
{   
    while (isDisplayThreadRunning)
    {
        Global.mainWindow.Dispatcher.Invoke(new Action(delegate()
        {
            for (int i = 0; i < numOfCamera; i++)
            {
                BitmapSource img = bitmapQueue[i].Serve(); //Pop the frame from Queue
                ControlDisplay[i].DrawImage(img); //Draw this frame on ControlDisplay[i]
            }
        }));
    }
}

当相机数量很大(> 15相机)时遇到问题,那么UI线程对用户的交互来说非常慢。

我知道显示许多摄像机视频时UI线程很重要。但我不知道如何改进它。有人可以告诉我,如何解决这个问题。

非常感谢!

2 个答案:

答案 0 :(得分:0)

不要在一次调用中绘制所有相机。这将阻止gui线程太长时间。你最好每次摄像头调用调用。或至少最多4批次。

您可以将Serve()方法从调用中移出并将其存储在字典中并使用DispatcherTimer进行更新。

<强>伪:

// hold the camera images.
public class CameraImage
{
    public bool Updated {get; set; }
    public BitmapSource Image {get; set; }
}

// cache
private Dictionary<int, CameraImage> _cameraCache = new Dictionary<int, CameraImage>();


// thread method to get the images.
while (isDisplayThreadRunning)
{
    for (int i = 0; i < numOfCamera; i++)
    {
        BitmapSource img = bitmapQueue[i].Serve(); //Pop the frame from Queue
        lock(_cameraCache)
        {
            CameraImage currentCameraImage;
            if(!_cameraCache.TryGetValue(i, out currentCameraImage))
            {
                _cameraCache.Add(i, currentCameraImage = new CameraImage());
            }
            currentCameraImage.Image = img;
            currentCameraImage.Updated = true;
        }
    }
}

// index cycler
private int _index;

// display timer.
public void DispatcherTimeMethod()
{
    lock(_cameraCache)
    {
        CameraImage currentCameraImage;

        if(_cameraCache.TryGetValue(_index, out currentCameraImage))
            if(currentCameraImage.Updated)
            {
                ControlDisplay[_index].DrawImage(currentCameraImage.Image);
                currentCameraImage.Updated = false;
            }
    }

    _index++;
    if(_index >= MAXCAMERAS)
        _index = 0;
}

如果相机(全部在一起)将生成太多图像,它将自动跳过图像。

答案 1 :(得分:0)

目前,您正在一个线程(UI线程)中更新所有相机。这使得UI线程始终冻结,即使您没有注意到它。

我建议使用Parallel.For来更新(多个)单独线程上的摄像头,然后使用UI调度程序更新UI上的图像。

这样的事情:

while ( isDisplayThreadRunning ) {

        //start a new parallel for loop
        Parallel.For( 0, numOfCamera, num => {
           BitmapSource img = bitmapQueue[i].Serve(); //Pop the frame from Queue

           //draw the new image on the UI thread
           Global.mainWindow.Dispatcher.Invoke(
              new Action( delegate
              {
                 ControlDisplay[i].DrawImage( img ); //Draw this frame on ControlDisplay[i]
              } ) );
        } );

        Thread.Sleep( 50 );//sleep if desired, lowers CPU usage by limiting the max framerate
     }
}