简体   繁体   English

保持UI线程响应能力?

[英]Keep the UI thread responsive?

My application is using WPF Control to display many video from Network Cameras. 我的应用程序使用WPF Control来显示来自网络摄像机的许多视频。

The summary code is below 摘要代码如下

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

I encountered an problem when the amount of camera is large (> 15 camera), then the UI thread is very slow for user's interaction. 当摄像机数量很大(> 15个摄像机)时,我遇到了一个问题,那么UI线程与用户的交互非常慢。

I know the UI thread works heavy when displaying many camera videos. 我知道在显示许多摄像机视频时,UI线程会很繁重。 But I don't know how to improve it. 但是我不知道如何改善它。 Someone can tell me, how to fix this issue. 有人可以告诉我如何解决此问题。

Many thanks! 非常感谢!

Don't draw all camera's in one invoke. 不要一次调用就绘制所有摄像机。 This will block the gui thread too long. 这将阻塞gui线程太长时间。 You'd better call invoke per camera draw. 您最好根据每次相机绘制调用调用。 Or atleast in batches of maximum 4. 或至少四个批次。


You might bring the Serve() method out of the invoke and store it in a dictionary and update it with a DispatcherTimer. 您可以将Serve()方法从调用中移除,并将其存储在字典中,并使用DispatcherTimer对其进行更新。

PSEUDO: 伪装:

// 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;
}

If the camera's (all together) will generate too many images, it will automatically skip images. 如果相机的(全部一起)生成太多图像,它将自动跳过图像。

Currently you are updating all your cameras in a single thread, the UI thread. 当前,您正在单个线程(UI线程)中更新所有摄像机。 This makes the UI thread always freeze, even if you don't notice it. 这使UI线程始终冻结,即使您没有注意到它。

What I'd recommend is using Parallel.For to update the camera feeds on (multiple) separate threads, then using the UI dispatcher to update the image on the UI. 我建议使用Parallel.For更新(多个)单独线程上的相机供稿,然后使用UI调度程序更新UI上的图像。

Something like this: 像这样:

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
     }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM