era*_*zap 5 c# wpf multithreading rendering
实施说明:
在每个CompositionTarget.Rendering事件中,我使用Writablebitmap绘制4条相邻的线条(这是"实时"线图的绘图仪).
问题:
这很有用,直到UI-Thread看起来很忙,然后下一个CompositionTarget.Rendering 事件需要更长时间才能触发.
题 :
是否有一些机制来保持一个恒定的渲染间隔,优先于任何其他UI操作?
可能的灵魂:
我正在考虑创建一个HostVisual以及如何为它分配一个DispatcherTimer,
这种方法会起作用吗?
想到的任何其他方法?
提前致谢 .
如果您已经渲染成 WritableBitmap,为什么不在 ThreadPool 上分拆一个异步任务呢?WritableBitmap 支持来自不同线程的更新,例如检查此问题或类文档备注上的信息。或者,如果您不喜欢线程池,则可以运行您自己的线程。这样您就可以控制时间,并且除了同步图像之外不需要依赖 UI 线程执行其他任何操作。
这是我刚刚编写的一些粗略的示例代码,应该可以让您了解我的意思:
public partial class MainWindow : Window
{
private WriteableBitmap mImage;
private bool mShutdown;
private object mUpdateLock = new object();
private IntPtr mBuffer;
private int mStride;
public MainWindow()
{
InitializeComponent();
mImage = new WriteableBitmap(10, 2, 96, 96, PixelFormats.Bgr32, null);
wImage.Source = mImage;
Closed += delegate {
CompositionTarget.Rendering -= CompositionTarget_Rendering;
lock (mUpdateLock)
{
mShutdown = true;
mImage.Unlock();
}
};
mImage.Lock();
mBuffer = mImage.BackBuffer;
mStride = mImage.BackBufferStride;
CompositionTarget.Rendering += CompositionTarget_Rendering;
UpdateAsync();
}
private void CompositionTarget_Rendering(object sender, EventArgs e)
{
lock (mUpdateLock)
{
// for a large image you can optimize that by only updating the parts that changed,
// collect dirty-areas in a list or something (while under the lock of course!)
mImage.AddDirtyRect(new Int32Rect(0, 0, 10, 2));
mImage.Unlock();
mImage.Lock();
// I don't know if these can changes, but docs say to acquire them after locking ...
mBuffer = mImage.BackBuffer;
mStride = mImage.BackBufferStride;
}
}
private async void UpdateAsync()
{
int x = 0;
int y = 0;
int color = 0xFF0000;
for (; ;)
{
lock (mUpdateLock)
{
if (mShutdown)
return;
// feel free to do 'unsafe' code here if you know what you're doing
Marshal.WriteInt32(new IntPtr(mBuffer.ToInt64() + x * 4 + y * mStride), color);
}
if (++x == 10)
{
x = 0;
if (++y == 2)
{
y = 0;
color ^= 0xFF00FF;
}
}
await Task.Delay(500).ConfigureAwait(false);
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread.Sleep(2000);
}
}
Run Code Online (Sandbox Code Playgroud)
以及对应的XAML
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Slow" HorizontalAlignment="Left" VerticalAlignment="Top" Click="Button_Click"/>
<Image x:Name="wImage"/>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)