【发布时间】:2014-11-14 17:05:09
【问题描述】:
我试图在另一个线程上渲染画布。这是我的尝试:
// returns path to exported image
private string exportToImage(double width, double height, Visual visual)
{
var filename = string.Format(@"{0}.png", Guid.NewGuid());
var tempFile = Path.Combine(tempDir, filename);
Rect rect = new Rect(0, 0, width, height);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right,
(int)rect.Bottom, 96d, 96d, System.Windows.Media.PixelFormats.Default);
Thread RENDER_THREAD = new Thread(() =>
{
this.Dispatcher.Invoke((Action)(() =>
{
rtb.Render(visual);
}));
});
RENDER_THREAD.Start();
//endcode as PNG
BitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(rtb));
//save to memory stream
System.IO.MemoryStream ms = new System.IO.MemoryStream();
pngEncoder.Save(ms);
ms.Close();
System.IO.File.WriteAllBytes(tempFile, ms.ToArray());
return tempFile;
}
我没有收到任何错误,但渲染结果是一个空图像。主线程和新线程中rtb的实例是否相同?
编辑: 这是我最近的尝试。
我在 MouseUp 事件上创建线程:
var curLayer = GetItemsPanel((canvasDataBinding.ItemContainerGenerator.ContainerFromIndex(Binding_LayersListView.SelectedIndex)));
Thread RASTERIZE_THREAD = new Thread(() => { exportToImage(curLayer.ActualWidth, curLayer.ActualHeight, curLayer); });
RASTERIZE_THREAD.Start();
这是我新线程使用的方法:
void exportToImage(double width, double height, Visual visual)
{
var filename = string.Format(@"{0}.png", Guid.NewGuid());
var tempFile = Path.Combine(tempDir, filename);
Rect rect = new Rect(0, 0, width, height);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right,
(int)rect.Bottom, 96d, 96d, System.Windows.Media.PixelFormats.Default);
this.Dispatcher.Invoke(new Action(() =>
{
rtb.Render(visual);
}));
//endcode as PNG
BitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(rtb));
//save to memory stream
System.IO.MemoryStream ms = new System.IO.MemoryStream();
pngEncoder.Save(ms);
ms.Close();
System.IO.File.WriteAllBytes(tempFile, ms.ToArray());
}
那么为什么它告诉我调用线程无法访问这个对象,因为另一个线程拥有它 rtb.Render(visual)?我没有从其他任何地方调用 exportToImage,那么为什么 Dispatcher 与我创建的线程没有关联?
编辑: 我需要在 Dispatcher.Invoke() 中创建 RebderTargetBitmap。
【问题讨论】:
-
两个问题!在线程中使用调度程序有效地使线程无用,其次不能保证线程在使用结果之前完成
BitmapFrame.Create(rtb) -
我想我明白了。那么我应该在 exportToImage 方法上创建一个新线程,然后在方法内部使用调度程序吗?
-
渲染时间是否太长?如果不是,则线程只是开销,如果是,则值得投资。其次,该方法是同步的,因为它需要一个渲染文件才能返回,因此使渲染函数异步将无济于事,因为该方法必须等到渲染完成。在这种情况下,该方法应该返回 void。
-
@pushpraj 是的,当我要渲染的画布上填充了太多图像并且画布的尺寸增加时,它需要很长时间。因此,为了使其异步,也许我可以将渲染图像的路径存储到某个共享缓冲区,然后在主线程中定期检查缓冲区。
标签: c# wpf multithreading wpf-controls dispatcher