[英]WriteableBitmap.Lock() Performance Issue
我有一個應用程序,使用WriteableBitmap
發生性能敏感的繪圖。 使用CompositionTarget.Rendering
調用事件以實際更新WriteableBitmap
的后台緩沖區。 從MSDN文檔中,這意味着在呈現控件之前每幀觸發一次事件。
我遇到的問題是WriteableBitmap的Lock()
函數需要很長時間,特別是在較大的位圖大小時。 我之前已經讀過AddDirtyRegion()
有一個錯誤導致整個位圖無效,導致性能不佳。 但是,這似乎並非如此。 從一個很好的低級檢查,似乎Lock()
打開位圖的后台緩沖區,用於在渲染線程上寫入,這意味着每次調用我的事件處理程序時,它都必須進行線程阻塞,直到渲染線程為它准備好。 這會在更新位圖圖形時導致明顯的延遲。
我已經嘗試使用TryLock()
向事件處理程序添加超時,這樣它就不會阻塞這么長時間並導致性能下降。 然而,這會產生類似的效果,因為它似乎滯后,因為大量的位圖更新被集中在一起。
以下是來自事件處理程序的相關代碼,以顯示我正在做什么。 編寫UpdatePixels()
函數是為了避免使用可能存在AddDirtyRect()
:
void updateBitmap(object sender, EventArgs e)
{
if (!form.ResizingWindow)
{
// Lock and unlock are important... Make sure to keep them outside of the loop for performance reasons.
if (canvasUpdates.Count > 0)
{
//bool locked = scaledDrawingMap.TryLock(bitmapLockDuration);
scaledDrawingMap.Lock();
//if (locked)
//{
unsafe
{
int* pixData = (int*)scaledDrawingMap.BackBuffer;
foreach (Int32Rect i in canvasUpdates)
{
// The graphics object isn't directly shown, so this isn't actually necessary. We do a sort of manual copy from the drawingMap, which acts similarly
// to a back buffer.
Int32Rect temp = GetValidDirtyRegion(i);
UpdatePixels(temp, pixData);
}
scaledDrawingMap.Unlock();
canvasUpdates.Clear();
}
//}
}
}
}
private unsafe void UpdatePixels(Int32Rect temp, int* pixData)
{
//int* pixData = (int*)scaledDrawingMap.BackBuffer;
// Directly copy the backbuffer into a new buffer, to use WritePixels().
var stride = temp.Width * scaledDrawingMap.Format.BitsPerPixel / 8;
int[] relevantPixData = new int[stride * temp.Height];
int srcIdx = 0;
int pWidth = scaledDrawingMap.PixelWidth;
int yLess = temp.Y + temp.Height;
int xLess = temp.X + temp.Width;
for (int y = temp.Y; y < yLess; y++)
{
for (int x = temp.X; x < xLess; x++)
{
relevantPixData[srcIdx++] = pixData[y * pWidth + x];
}
}
scaledDrawingMap.WritePixels(temp, relevantPixData, stride, 0);
}
我似乎無法弄清楚如何避免使用WriteableBitmap的線程阻塞問題,我在我編寫的代碼中看不到任何明顯的錯誤。 任何幫助或指針將不勝感激。
看起來你實際上並沒有使用BackBuffer來編寫 - 只是為了閱讀。
WritePixels寫入“前”緩沖區並且不需要鎖定。 我不知道你是否有其他理由來鎖定它(其他線程正在做某事),但對於那里的代碼我不明白為什么你需要。
我想我不需要鎖從BackBuffer(* pixData)讀取 - 我認為它只適用於寫入,但我很肯定你不需要為WritePixels調用Lock。
據我所知,你正在做:
切換3和4怎么樣?
WritePixels可能在內部導致渲染線程(在消息隊列中具有更高的優先級)代表它獲得鎖定,這可能是您所看到的延遲的一個因素。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.