首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WriteableBitmap死锁

WriteableBitmap死锁
EN

Stack Overflow用户
提问于 2014-03-05 23:53:49
回答 1查看 812关注 0票数 0

我正在使用WriteableBitmap来实现流式视频的视频显示(需要每秒重写多达30次)。

其中有几个在屏幕上,每个都有自己的视频显示。

视频也需要解码,所以我使用工作线程(每位图一个)进行解码和写入BackBuffer,然后用UI线程锁定AddDirtyRect并解锁如下

代码语言:javascript
运行
复制
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,我可以非常快地将它锁在两个线程上。有了一点睡眠,它就可以通过,但增加更多的线程将带来问题回来,我只能睡这么多之前,视频被放慢到低于实时速度(它必须是实时的)。

这种做法理应受到微软的鼓励。

http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap.lock(v=vs.110).aspx

我找到窃听器了吗?

如果我通过WritePixels写入前端缓冲区,就不会出现死锁,但为此,我需要多复制一次数据,并在WritePixels期间绑定GUI线程,因此,如果可能的话,我更愿意使用BackBuffer。

以下是运行两个线程时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) ...

EN

回答 1

Stack Overflow用户

发布于 2014-03-07 00:32:56

您所链接的页面还指出:

当呈现线程获得后缓冲区上的锁以将其向前复制到前面的缓冲区时,UI线程可以阻塞。如果来自这个块的延迟太长,请使用TryLock方法等待很短的时间,然后解除阻塞UI线程,以便在back缓冲区>被锁定时执行其他任务。

所以我假设你的一条线卡在那个锁里,就像他们说的。也许是这样的?

代码语言:javascript
运行
复制
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();
        });
    }

}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22212004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档