C#中的多线程问题

时间:2019-06-14 15:19:06

标签: c# multithreading winforms

我正在尝试在Windows窗体应用程序中以时间间隔来绘制数据图。

我需要在单独的线程上运行图形元素,但是我调用了三个不同的函数,不能简单地使用thread.start();

我尝试仅在其自己的线程中运行控件,但它告诉我另一个线程拥有控件。

按原样运行程序时,图表会严重滞后,这意味着它必须位于独立线程中

所有这些都需要在单独的线程上运行,因为更新时我的表单滞后了

public void GraphData()
{
    var mapper = Mappers.Xy<MeasureModel>()
    .X(model => model.DateTime.Ticks)   //use DateTime.Ticks as X
    .Y(model => model.Value);           //use the value property as Y

    Charting.For<MeasureModel>(mapper);

    //the ChartValues property will store our values array
    ChartValues = new ChartValues<MeasureModel>();
    cartesianChart1.Series = new SeriesCollection
    {
        new LineSeries
        {
            Values = ChartValues,
            PointGeometrySize = 1,
            StrokeThickness = 2
        }
    };

    cartesianChart1.AxisX.Add(new Axis
    {
        DisableAnimations = true,
        LabelFormatter = value => new System.DateTime((long)value).ToString("hh:mm:ss"),
        Separator = new Separator
        {
            Step = TimeSpan.FromSeconds(1).Ticks
        }
    });

    var thread = new Thread(() =>
    {

        SetAxisLimits(System.DateTime.Now);

        Timer = new System.Windows.Forms.Timer
        {
            Interval = 20

        };

        Timer.Tick += TimerOnTick;
        Timer.Tick += timerdata_event;
        Timer.Start();
    });
    thread.Start();
}

public ChartValues<MeasureModel> ChartValues { get; set; }
public System.Windows.Forms.Timer Timer { get; set; }

private void SetAxisLimits(System.DateTime now)
{
    cartesianChart1.AxisX[0].MaxValue = now.Ticks + TimeSpan.FromMilliseconds(1000).Ticks; // force the axis to be 100ms ahead
    cartesianChart1.AxisX[0].MinValue = now.Ticks - TimeSpan.FromSeconds(4).Ticks; // only care about the last 8 seconds
}

private void TimerOnTick(object sender, EventArgs eventArgs)
{
    var now = DateTime.Now;
    var queue = new Queue(tempStore);
    var b = queue.Dequeue();

    ChartValues.Add(new MeasureModel
    {
        DateTime = now,
        Value = double.Parse(b.ToString())
    });

    SetAxisLimits(now);

    if (ChartValues.Count > 100) ChartValues.RemoveAt(0);
}

2 个答案:

答案 0 :(得分:0)

看看BackgroundWorker。它是一个系统组件,它允许线程过程异步执行其工作,并提供两个在UI线程上运行的回调事件(ProgressChanged,RunWorkerCompleted)。

答案 1 :(得分:0)

有两件事... 1. Windows窗体使用队列而不是线程,它建立在STA(单线程建筑师)事件上,尽​​管当我们看它时,它看起来像MTA ... 因此,第一件事,如果您在单独的线程中运行,则应与Windows队列同步...如果在使用控件时不这样做,有时甚至会导致错误

致电:this (which this mean this form instance)

this.Invoke(new Action(delegate(){ /* your Synchronized code comes here */}))
        or (Action)delegate() {} as i saw in internet

第二次将计算放在背景上,执行双重缓冲之类的操作……意味着您在执行计算或绘图时既不应用也不与表单同步...

完成后,您只需应用确实在背面绘制的内容即可。...

因此您的最终代码将如下所示:

{ //New thread function
    // Calculates
    // Draw arts
    // Synchronize
    this.Invoke((Action)delegate() {
        //Perform Synchronizing Code
        // Apply your drawn image and graphics to your image viewer, aka picture box
    }
    // End of thread, or if you need something extra to be performed afterward...
}

但是,如果您无权访问该组件抽屉,请尝试查看性能。如果在后台传递参数,然后将其添加到表单中?如果初始化组件的过程比运行时更改图形的过程要少,如果看起来不错,请按照这种方式进行操作,导致在您插入某个组件时,每次更改都会导致表单重新绘制,并且会带来性能损失。