简体   繁体   中英

Multi-threading issue in c#

I am trying to graph data with Interval timing in my Windows Forms Application.

I need the graphing elements to be ran on a separate thread, but I have three different functions being called and cant simply use thread.start();

I tried running just the controls in it's own thread but it tells me that another thread owns the controls.

When I run the program as is, the chart lags horribly, meaning it needs to be in an independent thread

This all needs to be ran on a seperate thread because my form lags when updating this

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);
}

Take a look at BackgroundWorker . It's a system component that allows a threaded procedure to do its work asynchronously and provides two callback events (ProgressChanged, RunWorkerCompleted) that are run on the UI thread.

there are two things ... 1. windows form use queue not threading, and it's build on STA (Single Thread Architect) event though when we look at it, it look like MTA... So first thing, if you run in separate thread, you should synchronize with windows queue... it sometime even cause errors if you don't do that when you work with controls

calling: 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

Second put calculation on background, perform something such as dual buffering... mean you don't neither apply, nor synchronize with your form, while you are performing calculation or drawings...

once you are done, you just apply does are drawn in the back....

So your end code will be like this:

{ //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...
}

But if you do not have access to that component drawer.... try see how the performance look like, if you pass it parameters in the background, then add it to your form? if the processing of initializing the component is lower than changing graphic while running, if that looked good, go with that way, cause when you draw in some component, every change cause the form to redraw, and it comes with performance penalty.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM