简体   繁体   English

c#中的多线程问题

[英]Multi-threading issue in c#

I am trying to graph data with Interval timing in my Windows Forms Application. 我试图在我的Windows窗体应用程序中使用Interval计时来绘制数据。

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(); 我需要在一个单独的线程上运行图形元素,但我有三个不同的函数被调用,不能简单地使用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 . 看看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. 它是一个系统组件,允许线程过程异步执行其工作,并提供在UI线程上运行的两个回调事件(ProgressChanged,RunWorkerCompleted)。

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 有两件事...... 1.窗体使用队列而不是线程,它建立在STA(单线程架构师)事件上,虽然当我们看它时,它看起来像MTA ......所以首先,如果你分开运行线程,您应该与Windows队列同步...如果您在使用控件时不这样做,有时甚至会导致错误

calling: this (which this mean this form instance) 调用: 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. 如果初始化组件的处理低于运行时更改图形的处理,如果看起来不错,那么就这样,因为当你绘制某个组件时,每次更改都会导致表单重绘,并且会带来性能损失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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