C#异步LCD写入 [英] C# asynchronous LCD write
问题描述
因此,我正在从事一个涉及LCD屏幕的项目,该屏幕每秒可以更新60次.它使用 BitmapFrame
,我需要将这些像素复制到更新屏幕的库中.目前,我的FPS约为30-35,这太低了.因此,我尝试使用多线程,但这会带来很多问题.
So I'm working on a project that involves a LCD screen that can update 60 times per second. It uses a BitmapFrame
and I need to copy those pixels to a library that updates the screen. Currently I'm getting about 30-35 FPS which is too low. So I'm trying to use multi-threading but this creates a lot of problems.
DisplayController已经创建了一个thead来完成所有工作,如下所示:
The DisplayController already creates a thead to do all the work on like so:
public void Start()
{
_looper = new Thread(Loop);
_looper.IsBackground = true;
_looper.Start();
}
private void Loop()
{
while (_IsRunning)
{
renderScreen();
}
}
将调用 renderScreen
方法,该方法绘制所有元素并将像素复制到 BitmapFrame
.但是此过程花费的时间太长,因此我的FPS下降了.我试图解决此问题的方法是创建一个 Task
来绘制,复制和写入像素.但是此解决方案使用大量CPU,并导致屏幕出现故障.
Which calls the renderScreen
method that draws all the elements and copies the pixels to the BitmapFrame
. But this proces takes too long so my FPS drops. My attempt to solve this problem was by creating a Task
that draws, copies and writes the pixels. But this solution uses a lot of CPU and causes glitchtes on the screen.
public void renderScreen()
{
Task.Run(() =>
{
Monitor.Enter(_object);
// Push screen to LCD
BitmapFrame bf = BitmapFrame.Create(screen);
RenderOptions.SetBitmapScalingMode(bf, BitmapScalingMode.LowQuality);
bf.CopyPixels(new Int32Rect(0, 0, width, height), pixels, width * 4, 0);
DisplayWrapper.USBD480_DrawFullScreenBGRA32(ref disp, pixels);
Monitor.Exit(_object);
});
}
我已经阅读了很多有关C#并发队列的信息,但这不是我所需要的.使用两个线程会导致编译器说该变量归另一个线程所有的问题.
I've been reading a lot about concurrent queues for C# but that's not what I need. And using two threads causes the issue that the compiler says that the variable is owned by another thread.
如何同时渲染新的位图并将该位图每秒写入LCD 60次?
How can I concurrently render a new bitmap and write that bitmap 60 times per second to the LCD?
推荐答案
我认为您应该有两个线程(并且只有两个):
I think you should have two threads (and two only):
- 一个连续创建位图的对象;和
- 一个连续获取最新位图并将其推到LCD的人.
这是我幼稚的实现方式.
Here's my naive implementation.
我使用了一个共享阵列,其中包含最新生成的图像,因为它使分配数保持较低.一个共享数组我们可以摆脱3个数组对象(共享+ 2个线程局部变量).
I used a shared array that contains the latest produced image because it keeps number of allocations low. A shared array we can get away with 3 array objects (shared + 2 thread locals).
public class Program
{
public class A
{
private readonly object pixelsLock = new object();
Array shared = ...;
public void Method2()
{
Array myPixels = (...);
while (true)
{
// Prepare image
BitmapFrame bf = BitmapFrame.Create(screen);
RenderOptions.SetBitmapScalingMode(bf, BitmapScalingMode.LowQuality);
bf.CopyPixels(new Int32Rect(0, 0, width, height), myPixels, width * 4, 0);
lock (pixelsLock)
{
// Copy the hard work to shared storage
Array.Copy(sourceArray: myPixels, destinationArray: shared, length: myPixels.GetUpperBound(0) - 1);
}
}
}
public void Method1()
{
Array myPixels = (...);
while (true)
{
lock (pixelsLock)
{
//Max a local copy
Array.Copy(sourceArray: shared, destinationArray: myPixels, length: myPixels.GetUpperBound(0) - 1);
}
DisplayWrapper.USBD480_DrawFullScreenBGRA32(ref disp, myPixels);
}
}
}
public static async Task Main(string[] args)
{
var a = new A();
new Thread(new ThreadStart(a.Method1)).Start();
new Thread(new ThreadStart(a.Method2)).Start();
Console.ReadLine();
}
}
这篇关于C#异步LCD写入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!