通过一些帮助,我设法创建了一个新线程,虽然该方法似乎执行,但该方法的条件要么出现绿灯或红灯,尽管在运行方法(Check1..etc)时没有新的线程更改反映在GUI上(例如红色/绿灯出现),但在创建新线程并运行方法时,更改不会反映在表单/ GUI上。
// Method / Action to start the checks private void StartChecks_Click(object sender, EventArgs e)
{
Thread t = new Thread(
o =>
{
InitChecks();
});
t.Start();
}
// Check1 public void Check1()
{
// lets grabs the info from the config!
var lines = File.ReadAllLines("probe_settings.ini");
var dictionary = lines.Zip(lines.Skip(1), (a, b) => new { Key = a, Value = b })
.Where(l => l.Key.StartsWith("#"))
.ToDictionary(l => l.Key, l => l.Value);
// lets set the appropriate value for this check field
label1.Text = dictionary["#CheckName1"];
// lets define variables and convert the string in the dictionary to int for the sock.connection method!
int portno1;
int.TryParse(dictionary["#PortNo1"], out portno1);
// Convert hostname to IP, performance issue when using an invalid port on a hostname using the TcpClient class!
IPAddress[] addresslist = Dns.GetHostAddresses(hostname2);
foreach (IPAddress theaddress in addresslist)
{
// Attempt to create socket and connect to specified port on host
TcpClient tcP = new System.Net.Sockets.TcpClient();
try
{
tcP.ReceiveTimeout = 1;
tcP.SendTimeout = 1;
tcP.Connect(theaddress, portno1);
displayGreen1();
tcP.Close();
}
catch
{
displayRed1();
}
}
}
// Change the lights when the condition is met
public void displayGreen1()
{
pictureBox2.Visible = false;
pictureBox1.Visible = true;
}
private void displayRed1()
{
pictureBox2.Visible = true;
pictureBox1.Visible = false;
}
答案 0 :(得分:3)
这就是WinForms的设计方式。您无法从其他线程进行更改。 解决方案通常是使用异步委托。
首先添加此声明
public delegate void MyDelegate1 ();
public delegate void MyDelegate2 ();
然后当你在另一个线程中时你应该这样做:
MyDelegate1 d1= new MyDelegate1 (displayGreen1);
this.BeginInvoke(d1);
MyDelegate2 d2= new MyDelegate2 (displayRed1);
this.BeginInvoke(d2);
答案 1 :(得分:2)
在您的技能水平上,最好是:
bool _pb1Visible
和bool _pb2Visible
)它会像魅力一样发挥作用!
简单示例:
在Check1()
方法中,而不是:
displayGreen1();
把
_pb1Visible=true;
_pb1Visible=false;
而不是
displayRed1();
把
_pb1Visible=false;
_pb1Visible=true;
将计时器放在表单上。在计时器事件中,执行:
pictureBox2.Visible = _pb2Visible;
pictureBox1.Visible = _pb1Visible;
答案 2 :(得分:2)
这种情况正在发生,因为UI控件只能从UI线程更新。当不创建新线程时,更新控件的代码将在UI线程上运行,因此它可以按预期工作。当你做创建一个新线程时,因为这个线程不是 UI线程,所以应该更新控件的代码不能这样做。
通过将方法调用更改为: -
,可以确保更新控件的代码在UI线程上运行this.BeginInvoke(new Action(() => displayRed1()));
和
this.BeginInvoke(new Action(() => displayGreen1()));
顺便说一句(与您当前的问题无关): -
尽量避免创建显式线程。而是使用线程池为您管理线程,例如ThreadPool.QueueUserWorkItem(x => InitChecks())
。 (请注意,这仍将在非UI线程上运行,因此您仍需要使用BeginInvoke()
,如上所述。)。线程池最了解何时创建和执行线程并最终使用它将使代码更有效。
尽量避免在try{...}catch{...}
中捕获所有异常类型。这表明当您抛出任何类型的异常时,您的代码知道该怎么做。相反,只捕获您确切知道如何处理的异常,
e.g。
try
{
...
}
catch(TcpException)
{
...
}
catch(AnotherKnownException)
{
...
}
...
请注意,只要在退出块时重新抛出异常,就可以为所有异常类型设置catch
块,
e.g。
try
{
...
}
catch(KnownException)
{
...
}
catch(Exception)
{
// perform some logging, rollback, etc.
throw;
}