繁体   English   中英

WriteableBitmap死锁

[英]WriteableBitmap deadlock

我正在使用WriteableBitmap来实现流式视频的视频显示(需要将其每秒最多重写30次)
屏幕上有多个视频,每个视频都有自己的视频显示。
视频也需要解码,因此我使用工作线程(每个位图一个)进行解码并写入BackBuffer,然后将UI线程锁定为AddDirtyRect和Unlock,如下所示

m_WrtblBtmp.Dispatcher.Invoke(() =>
{
    Debug.WriteLine("About to lock Bitmap" + m_WrtblBtmp.GetHashCode().ToString());
    m_WrtblBtmp.Lock();                     
});


if (ReadNextVideoFrame(m_VideoDecoder, m_BackBuffer))
{
    m_WrtblBtmp.Dispatcher.Invoke(() => 
    {
        Debug.WriteLine("About to dirty up Bitmap" + m_WrtblBtmp.GetHashCode().ToString());
        m_WrtblBtmp.AddDirtyRect(new Int32Rect(0, 0, 1280, 1024));
    });
}

m_WrtblBtmp.Dispatcher.Invoke(() => 
{
    Debug.WriteLine("About to Unlock Bitmap" + m_WrtblBtmp.GetHashCode().ToString());
    m_WrtblBtmp.Unlock();
});

ReadNextVideoFrame通过m_BackBuffer指针(WriteableBitmap.BackBuffer的副本)获取,解码视频帧并将其写入位图。我遇到的问题是,一旦您拥有足够的线程,该东西就会死锁。 没有Thread.Sleep,我可以很快将其在2个线程上死锁。 稍加睡眠即可解决问题,但增加更多线程将使问题再次出现,并且我只能睡很多时间才能将视频放慢到低于实时速度(必须直播)。

据说这种做法是微软鼓励的
http://msdn.microsoft.com/zh-cn/library/system.windows.media.imaging.writeablebitmap.lock(v=vs.110).aspx
我找到错误了吗?

如果我通过WritePixels写入前端缓冲区,则不会出现死锁,但是为此,我需要额外复制一次数据,并在WritePixels期间占用GUI线程,因此如果可以的话,我宁愿使用BackBuffer。

这是运行2个线程时Debug.WriteLine的输出:
About to lock Bitmap53653601 About to lock Bitmap31265986 About to dirty up Bitmap53653601 About to dirty up Bitmap31265986 About to Unlock Bitmap53653601 About to Unlock Bitmap31265986 ... more of the same ... About to dirty up Bitmap50546581 About to Unlock Bitmap50546581 About to dirty up Bitmap9315575 About to lock Bitmap50546581 About to Unlock Bitmap9315575 About to lock Bitmap9315575 About to dirty up Bitmap50546581 About to Unlock Bitmap50546581 About to dirty up Bitmap9315575 About to lock Bitmap50546581 ... then nothing (deadlock) ...

您链接的页面还显示以下内容:

UI线程可以在渲染线程获得后缓冲区的锁以将其向前复制到前缓冲区时锁定。 如果此块的延迟时间太长,请使用TryLock方法等待一小段时间,然后在后台缓冲区>锁定的同时取消阻止UI线程执行其他任务。

所以我想像他们说的那样,您的线程之一卡在了那个锁中。 也许像这样?

while (SomethingIsTrue) // i'm presuming you have a loop like this already?)
{
    bool gotLock = false;

    m_WrtblBtmp.Dispatcher.Invoke(() =>
    {
        Debug.WriteLine("About to try to lock Bitmap" + m_WrtblBtmp.GetHashCode().ToString());
        gotLock = m_WrtblBtmp.TryLock(SomeTimeoutConstant);                     
        Debug.WriteLine((gotLock ? "got lock on " : "DID NOT lock ") + m_WrtblBtmp.GetHashCode().ToString());

    });

    if (gotLock && ReadNextVideoFrame(m_VideoDecoder, m_BackBuffer))
    {
        m_WrtblBtmp.Dispatcher.Invoke(() => 
        {
            Debug.WriteLine("About to dirty up Bitmap" + m_WrtblBtmp.GetHashCode().ToString());
            m_WrtblBtmp.AddDirtyRect(new Int32Rect(0, 0, 1280, 1024));
            Debug.WriteLine("About to Unlock Bitmap" + m_WrtblBtmp.GetHashCode().ToString());
            m_WrtblBtmp.Unlock();
        });
    }

}

暂无
暂无

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

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