En essayant de rendre un canevas sur un autre fil. Voici ma tentative:Comment faire pour rendre un visuel sur un autre thread
// 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;
}
Je ne reçois aucune erreur mais le résultat rendu est une image vide. L'instance de rtb
dans le thread principal et le nouveau thread est-elle la même?
Modifier: Voici ma dernière tentative.
je crée le fil sur un événement MouseUp:
var curLayer = GetItemsPanel((canvasDataBinding.ItemContainerGenerator.ContainerFromIndex(Binding_LayersListView.SelectedIndex)));
Thread RASTERIZE_THREAD = new Thread(() => { exportToImage(curLayer.ActualWidth, curLayer.ActualHeight, curLayer); });
RASTERIZE_THREAD.Start();
et voici ma méthode le nouveau thread utilise:
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());
}
Alors pourquoi est-il me dire que Le thread appelant ne peut pas accéder cet objet parce qu'un thread différent le possède sur rtb.Render(visual)
? Je n'appelle pas exportToImage d'ailleurs, alors pourquoi Dispatcher n'est-il pas associé au thread que j'ai créé?
Modifier: J'avais besoin de créer le RebderTargetBitmap à l'intérieur de Dispatcher.Invoke().
deux problèmes! utiliser le répartiteur dans le thread rend effectivement le thread inutile, d'autre part, il n'y a aucune garantie que le thread se termine avant que le résultat ne soit utilisé ici 'BitmapFrame.Create (rtb)' – pushpraj
Je pense que je comprends. Donc dois-je créer un nouveau thread sur la méthode exportToImage, puis utiliser le répartiteur dans la méthode? – Infodayne
cela prend-il trop de temps à rendre? Si non alors le fil est juste un frais généraux, si oui alors l'effort vaut la peine d'investir. deuxièmement, la méthode est synchrone car elle a besoin d'un fichier rendu à retourner, donc rendre la fonction de rendu asynchrone n'aidera pas car la méthode doit attendre jusqu'à ce que le rendu soit terminé. dans ce cas, la méthode devrait renvoyer void. – pushpraj