Im пытается сделать холст в другом потоке. Вот моя попытка:Как визуализировать визуализацию в другом потоке
// 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 из другого места, так почему Диспетчер не связан с созданным мной потоком?
Редактировать: Мне нужно было создать RebderTargetBitmap внутри Dispatcher.Invoke().
две проблемы! использование диспетчера в потоке эффективно делает поток бесполезным, во-вторых, нет гарантии, что поток завершится до того, как результат будет использован здесь. «BitmapFrame.Create (rtb)» – pushpraj
Я думаю, что понимаю. Так должен ли я создать новый поток в методе exportToImage, а затем использовать диспетчер внутри метода? – Infodayne
Делать это слишком долго? если нет, то поток - это просто накладные расходы, если да, то усилия стоит инвестировать. во-вторых, метод является синхронным, так как ему нужен возвращенный файл рендеринга, поэтому сделать функцию рендеринга async не поможет, поскольку метод должен ждать завершения рендеринга. в этом случае метод должен возвращать void. – pushpraj