0

我想使用 wpf 工具包图表将大量点显示为图表(至少 300 000 个点)。

我有以下 XAML

<chartingToolkit:Chart Name="chartHistory">
    <chartingToolkit:Chart.Axes>
        <chartingToolkit:LinearAxis x:Name="horizontalAxis" Orientation="X" Title="Time [s]"  ShowGridLines="True"/>
        <chartingToolkit:LinearAxis x:Name="verticalAxis" Orientation="Y" Title="Value [mm]"  ShowGridLines="True"/>
    </chartingToolkit:Chart.Axes>
    <chartingToolkit:AreaSeries x:Name="chartSeries" DataPointStyle="{StaticResource chartDataPoint}"
        IndependentValuePath="TimeInSeconds"
        DependentValuePath="Value">
    </chartingToolkit:AreaSeries>
</chartingToolkit:Chart>

在后面的代码中:

public class PointData
{
    public double TimeInSeconds { get; set; }
    public double Value { get; set; }
}

private List<PointData> points;

private void Screen_Loaded(object sender, RoutedEventArgs e)
{
    // this is a large collection of points (minimum 300 000)
    points = LoadPointsFromFile();

    // and it takes a lot of time to read from the file and load in the UI
    chartSeries.ItemsSource = points;

    // additional chart display properties (setting min/max on the axes etc.)
}

所以,我有 2 个耗时的操作阻塞了我的 UI。我想要的是在耗时操作发生时显示“请加载对话框”,以便用户知道应用程序仍在执行某些操作。

耗时的操作是:

  1. 从文件中读取点(这个操作可以在单独的线程上完成,但是由于下一个操作(加载图表中的点)取决于它并且是UI操作,所以我没有把它放在单独的线程中)
  2. 在图表中将点加载为 ItemsSource - 这是一个 UI 操作,应该在 UI 线程上完成。但是,由于我无法控制点的显示方式,我怎样才能使应用程序仍然响应 - 这是图表自己的逻辑?

那么,有什么想法吗?你有过类似的问题吗?谢谢你,纳迪亚

4

1 回答 1

0

实际上,我所做的是创建一个单独的线程,该线程显示一个不同的“加载对话框”,该对话框在数据加载时显示。从对话框关闭到 UI 完全响应还有大约一秒钟的时间,但这仍然比查看无响应的 UI 5-10 秒要好。

public class PointData
{
    public double TimeInSeconds { get; set; }
    public double Value { get; set; }
}

#region Wait Dialog Thread
private class MainWindowSize
{
    public double Left;
    public double Top;
    public double Width;
    public double Height;
}

private Thread newWindowThread = null;

private void ThreadStartingPoint(object obj)
{
    // WaitDialog is a new window from your project - you can place a animation or message inside it
    WaitDialog tempWindow = new WaitDialog();

    // since we don't have an owner for the window, we need
    // to compute the location of the popup dialog, so that
    // its centered inside the main window
    MainWindowSize wndSize = obj as MainWindowSize;
    if (wndSize != null)
    {
        tempWindow.Left = wndSize.Left + wndSize.Width / 2 - tempWindow.Width / 2;
        tempWindow.Top = wndSize.Top + wndSize.Height / 2 - tempWindow.Height / 2;
    }

    // it's very important not to set the owner of this dialog
    // otherwise it won't work in a separate thread
    tempWindow.Owner = null;

    // it shouldn't be a modal dialog
    tempWindow.Show();
    tempWindow.Closed += (sender1, e1) => tempWindow.Dispatcher.InvokeShutdown();
    System.Windows.Threading.Dispatcher.Run();
}

private void CreateAndStartWaitWindowThread()
{
    // create a thread only if you don't have an active one 
    if (newWindowThread == null)
    {
        // use ParameterizedThreadStart instead of ThreadStart
        // in order to send a parameter to the thread start method
        newWindowThread = new Thread(new ParameterizedThreadStart(ThreadStartingPoint));
        newWindowThread.SetApartmentState(ApartmentState.STA);
        newWindowThread.IsBackground = true;

        // get the properties of the window, in order to compute the location of the new dialog
        Window mainWnd = App.CurrentApp.MainWindow;     
        MainWindowSize threadParams = new MainWindowSize { Left = mainWnd.Left, Top = mainWnd.Top, Width = mainWnd.ActualWidth, Height = mainWnd.ActualHeight };

        // start thread with parameters
        newWindowThread.Start(threadParams);
    }
}

private void AbortAndDeleteWaitWindowThread()
{
    // abort a thread only if you have an active one 
    if (newWindowThread != null)
    {
        newWindowThread.Abort();
        newWindowThread = null;
    }
}
#endregion

private List<PointData> points;

private void Screen_Loaded(object sender, RoutedEventArgs e)
{
    try
    {
        // call this before long operation
        this.Cursor = Cursors.Wait;
        CreateAndStartWaitWindowThread();

        // this is a large collection of points (minimum 300 000)
        points = LoadPointsFromFile();

        // and it takes a lot of time to read from the file and load in the UI
        chartSeries.ItemsSource = points;

        // additional chart display properties (setting min/max on the axes etc.)
    }
    catch(Exception ex)
    {
        // do something with the exception
    }
    finally
    {
        // call this after long operation - and make sure it's getting called
        // so put it in the finally block - to call it even if an exception is raised
        this.Cursor = Cursors.Arrow;
        AbortAndDeleteWaitWindowThread();
    }
}

来源:http ://www.c-sharpcorner.com/uploadfile/suchit_84/creating-wpf-windows-on-dedicated-threads/

于 2013-09-02T12:46:51.323 回答