-1

我正在做一个学校项目,我需要做一些温度测量。任务是随机创建一些温度,然后计算平均值。我的代码如下,但是线程有问题。在创建窗口句柄之前,它不能被称为对象。我搜索了网络,发现后台工作人员对于更新 UI 更有用。我还没有那么熟练的编程,因为我刚开始上学。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using System.Threading;

namespace Temperatur
{
    public partial class Form1 : Form
    {
        static Random rnd = new Random();
        static ArrayList tempList = new ArrayList();
        static SemaphoreSlim w, e, b;

        public Form1()
        {
            InitializeComponent();

            w = new SemaphoreSlim(1);
            e = new SemaphoreSlim(0);
            b = new SemaphoreSlim(6);

            Thread t1 = new Thread(randomNr);
            t1.Start();

            Thread t2 = new Thread(gennemsnit);
            t2.Start();
        }

        public void randomNr()
        {
            //Thread.Sleep(100);
            for (int i = 0; i < 10; i++)
            {
                //b.Wait();
                //w.Wait();
                int number = rnd.Next(36, 42);
                tempList.Add(number);

                listBox1.BeginInvoke((MethodInvoker)delegate
                {
                    listBox1.Items.Add(number);
                });
                //w.Release();
                //e.Release();
            }
        }

        public void gennemsnit()
        {
            double avg = 0;
            double nb = 0;
            //Thread.Sleep(200);

            for (int i = 0; i < tempList.Count; i++) //i < tempList.Count
            {
                //e.Wait();
                //w.Wait();
                nb += Convert.ToDouble(tempList[i]);
                avg = nb / tempList.Count;

                listBox2.Invoke((MethodInvoker)delegate //listbox2.invoke
                {
                    listBox2.Items.Add(avg);
                });
                //w.Release();
                //b.Release();
            }
        }
    }
}
4

3 回答 3

0

BackgroundWorker 确实是您所需要的。如果您“报告进度”,您可以在进度报告中将对象传递给 GUI 线程。像这样设置进度报告:

    BackgroundWorker bw = new BackgroundWorker();

...

        bw.WorkerReportsProgress = true;
        bw.DoWork += bw_DoWork;
        bw.ProgressChanged += bw_ProgressChanged;

...

        void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // Here you have passed yourself any object you like. Could be your own class. Could be a string, etc.
    MyClass myObject = e.UserState as MyClass;


    // Then you can add it to your GUI as necessary, for example
    listbox2.Items.Add(myObject);    
}

您可能只想将字符串作为对象传递,然后将该字符串添加到列表框中。

于 2013-11-06T13:59:13.357 回答
0

我不确定您的代码要做什么,但您的任务很简单。你真的不必担心线程。为简单起见,您可以安排一个计时器每隔 1 秒运行一次,然后选择一个随机数/读取温度并在 UI 上更新它。如果您从表单控件 (System.Windows.Forms.Timer) 中选择计时器,那么您可以直接从它触发时调用的函数更新 UI。如果您使用 System.Timers.Timer 中的计时器,则应使用 BeginInvoke 更新列表。

于 2013-11-06T14:06:17.153 回答
0

在创建窗口句柄之前,它不能被称为对象。

不要在 Form 的构造函数中启动线程。请改用 Load() 或 Shown() 事件:

    public Form1()
    {
        InitializeComponent();

        w = new SemaphoreSlim(1);
        e = new SemaphoreSlim(0);
        b = new SemaphoreSlim(6);

        this.Load += new EventHandler(Form1_Load);
    }

    void Form1_Load(object sender, EventArgs e)
    {
        Thread t1 = new Thread(randomNr);
        t1.Start();

        Thread t2 = new Thread(gennemsnit);
        t2.Start();
    }
于 2013-11-06T16:04:13.687 回答