我在一个学校项目上工作,我需要做一些温度测量。任务是随机创建一些温度,然后计算平均值。我的代码如下,但我遇到了Threads的问题。在创建窗口句柄之前,不能将其称为对象。我在网上搜索,发现后台工作者对更新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();
}
}
}
}
答案 0 :(得分: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);
}
您可能只想传递一个字符串作为对象,然后将该字符串添加到列表框中。
答案 1 :(得分:0)
我不确定您的代码尝试做什么,但您的任务非常简单。你真的不必担心线程。为简单起见,您可以安排计时器运行每个1s并选择一个随机数/读取温度并在UI上更新它。如果从窗体控件(System.Windows.Forms.Timer)中选择计时器,则可以直接从触发时触发的函数更新UI。如果您使用System.Timers.Timer中的计时器,则应使用BeginInvoke更新列表。
答案 2 :(得分: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();
}