Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在内存中呈现Livecharts图表并另存为图像_C#_Wpf_Multithreading_Livecharts - Fatal编程技术网

C# 在内存中呈现Livecharts图表并另存为图像

C# 在内存中呈现Livecharts图表并另存为图像,c#,wpf,multithreading,livecharts,C#,Wpf,Multithreading,Livecharts,我正在努力做到以下几点: 在内存中创建Livechart笛卡尔图表 将图表添加到网格中 将标签添加到同一网格 将栅格添加到视口框中 将Viewbox渲染为PNG 将PNG保存到磁盘 以上内容应该在后台从不同的线程运行,以便实现UI响应 无论这看起来多么简单,我一直在努力找到一个合适的工作解决方案。以下问题是相关的: Livechart(位于Viewbox内)需要时间进行渲染 因此,在试图将图表保存为图像之前,需要给图表一段时间来完成渲染 我已经找到了使用HwndSource的代码,但是它不

我正在努力做到以下几点:

  • 在内存中创建Livechart笛卡尔图表
  • 将图表添加到网格中
  • 将标签添加到同一网格
  • 将栅格添加到视口框中
  • 将Viewbox渲染为PNG
  • 将PNG保存到磁盘
以上内容应该在后台从不同的线程运行,以便实现UI响应

无论这看起来多么简单,我一直在努力找到一个合适的工作解决方案。以下问题是相关的:

  • Livechart(位于Viewbox内)需要时间进行渲染
  • 因此,在试图将图表保存为图像之前,需要给图表一段时间来完成渲染
  • 我已经找到了使用HwndSource的代码,但是它不是一直工作的(大约95%的时间工作)。如果不修改HwndSource,它就永远不会工作(总是得到一个没有任何内容的图表)
  • 在不同的UI线程中运行Run()函数不起作用,因为我会收到以下错误消息:WPF Dispatcher{“调用线程无法访问此对象,因为其他线程拥有它。”}
因此,我的问题是:

  • 在将Livechart/Grid/ViewBox组合保存为图像之前,等待其完成渲染的正确方法是什么?也许可以利用加载的事件?请注意,我曾试图推动它,但无法让它工作,因为我碰到了“线程”问题
  • 如何在不同的UI线程中运行整个流程
代码见下文

public void Run()
(
   //Create Livechart which is a child of a Grid control
   Grid gridChart = Charts.CreateChart();
   //Creates a ViewBox control which has the grid as its child
   Viewbox viewBox = WrapChart(gridChart,1400,700);
   //Creates and saves the image
   CreateAndSaveImage(viewBox ,path,name);
)
下面是创建Viewbox并将栅格作为子项添加的函数

public Viewbox viewBox WrapChart(Grid grid,int width,int height)
{

    chart.grid.Width = width;
    chart.grid.Height = height;

    viewbox.Child = chart.grid;

    viewbox.Width = width;
    viewbox.Height = height;
    viewbox.Measure(new System.Windows.Size(width, height));
    viewbox.Arrange(new Rect(0, 0, width, height));
    viewbox.UpdateLayout();

}
下面的函数创建并保存图像

public void CreateAndSaveImage(Viewbox viewbox,string folderPath,string fileName)
{
    var x = HelperFunctions.GetImage(viewbox);
    System.IO.FileStream stream = System.IO.File.Create(folderPath + fileName);
    HelperFunctions.SaveAsPng(x, stream);
    stream.Close();   
}
以下代码将viewbox渲染为图像。请注意,这是我能找到的唯一等待图表完成加载的代码。我不知道它是怎么工作的,但95%的时间都是这样。有时图表仍然没有完成加载

public static RenderTargetBitmap GetImage(Viewbox view)
{

      using (new HwndSource(new HwndSourceParameters())
      {
          RootVisual =
                           (VisualTreeHelper.GetParent(view) == null
                                ? view
                                : null)
      })
      {

          Size size = new Size(view.ActualWidth, view.ActualHeight);
          if (size.IsEmpty)
              return null;


          int actualWidth = Convert.ToInt32(size.Width);
          int requiredWidth = Convert.ToInt32(size.Width * 1);

          int actualHeight = Convert.ToInt32(size.Height);
          int requiredHeight = Convert.ToInt32(size.Height * 1);

          // Flush the dispatcher queue
          view.Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() => { }));

          var renderBitmap = new RenderTargetBitmap(requiredWidth, requiredHeight,
                                                          96d * requiredWidth / actualWidth, 96d * requiredHeight / actualHeight,
                                                          PixelFormats.Pbgra32);


          DrawingVisual drawingvisual = new DrawingVisual();
          using (DrawingContext context = drawingvisual.RenderOpen())
          {
              context.DrawRectangle(new VisualBrush(view), null, new Rect(new Point(), size));
              context.Close();
          }

          renderBitmap.Render(view);
          renderBitmap.Freeze();

          return renderBitmap;
      }


}
以下代码将位图作为图片保存到文件

public static void SaveAsPng(BitmapSource src, Stream outputStream)
{
      PngBitmapEncoder encoder = new PngBitmapEncoder();
      encoder.Frames.Add(BitmapFrame.Create(src));

      encoder.Save(outputStream);
}
下面的代码是我用来在不同线程中运行整个程序的代码。请注意,它不起作用,因为我收到以下错误消息:

WPF Dispatcher{“调用线程无法访问此对象,因为 另一个线程拥有它。“}

请注意,如果我正常执行Run()(没有任何单独的线程),它可以工作,但是有时图表无法正确呈现(如前所述)


请尝试调用此行以查看图表:

    this.chart.Model.Updater.Run(false, true);

这条线会更新图表,并且在保存到图像时始终可见。

谢谢,伙计,不得不使用大量的解决方法才能使其正常工作。这么简单
    this.chart.Model.Updater.Run(false, true);