How to render a visual on another 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;
}
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.Invoke()内创建RebderTargetBitmap。
推荐答案
以下是如何在线程中呈现相同内容并使其异步的代码
整个想法是
- 将可视化序列化为XAML字符串
- 创建STA线程
- 然后让线程进行同样的反序列化。
- 将反序列化的可视内容承载在内容控件中,并进行排列等操作。
- 最后但并非最不重要的一点,呈现它(取自您的代码)
此代码不依赖于调度程序,因此能够完全异步运行
    void exportToImage(double width, double height, Visual visual)
    {
        //this line can not be inside a thread because different thread owns the visual
        string visualData = XamlWriter.Save(visual);
        Thread t = new Thread(() =>
            {
                var filename = string.Format(@"{0}.png", Guid.NewGuid());
                var tempFile = System.IO.Path.Combine("c:\", filename);
                Rect rect = new Rect(0, 0, width, height);
                //create a host control to host the visual
                ContentControl cc = new ContentControl();
                cc.Content = XamlReader.Parse(visualData);
                //call Arrange to let control perform layout (important)
                cc.Arrange(rect);
                RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right,
                    (int)rect.Bottom, 96d, 96d, System.Windows.Media.PixelFormats.Default);
                rtb.Render(cc);
                //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());
            });
        //STA is necessary for XamlReader.Parse, and proper rendering
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
    }
我已经成功地测试了这段代码以呈现一些测试视觉效果。但结果可能会因使用方式的不同而有所不同。据猜测,绑定&;光栅图像可能会有一些问题,但在我的测试中,它就像一个护身符。
这篇关于如何在另一个线程上呈现视觉效果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
				 沃梦达教程
				
			本文标题为:如何在另一个线程上呈现视觉效果
 
				
         
 
            
        基础教程推荐
             猜你喜欢
        
	     - 是否可以在 asp classic 和 asp.net 之间共享会话状态 2022-01-01
- 从 VS 2017 .NET Core 项目的发布目录中排除文件 2022-01-01
- 经典 Asp 中的 ResolveUrl/Url.Content 等效项 2022-01-01
- 全局 ASAX - 获取服务器名称 2022-01-01
- 将事件 TextChanged 分配给表单中的所有文本框 2022-01-01
- 错误“此流不支持搜索操作"在 C# 中 2022-01-01
- 首先创建代码,多对多,关联表中的附加字段 2022-01-01
- JSON.NET 中基于属性的类型解析 2022-01-01
- 如何动态获取文本框中datagridview列的总和 2022-01-01
- 在 VS2010 中的 Post Build 事件中将 bin 文件复制到物 2022-01-01
 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
						 
						 
						 
						 
						 
				 
				 
				 
				