当创建一个新的线程,没有被更改了GUI(C#)线程、改了、创建一个、GUI

2023-09-03 06:22:35 作者:醉过才知酒浓,爱过才知情重。今天小编特别设计一组适合男生用的

通过一些帮助,我已经成功地创建一个新线程,尽管该方法看起来执行,该方法的条件要么做一个绿色或红色的光出现,但如果没有新的运行方式(Check1..etc)时,线程变化反映在图形用户界面(如红色/绿色光时出现),但创建一个新的线程运行的方法时所做的更改不会对窗体/ GUI体现。

  //方法/措施来启动检查私人无效StartChecks_Click(对象发件人,EventArgs的)
        {

            线程t =新主题(
               O =>
               {
                   InitChecks();
               });
            t.Start();
        }

//检查1公共无效检查1()
        {

            //让抓斗从配置的信息!
            变种线= File.ReadAllLines(probe_settings.ini);
            VAR词典= lines.Zip(lines.Skip(1),(A,B)=>新建{键= A,值= B})
                                  。凡(升=> l.Key.StartsWith(#))
                                  .ToDictionary(升=> L.KEY,升=> l.Value);

            //让设置此检查字段中的相应值
            label1.Text =辞典[#CheckName1];

            //允许定义变量和转换字符串中的词典为int的sock.connection方法!

            INT portno1;
            int.TryParse(词典[#PortNo1],出portno1);

            //使用TcpClient类的主机名使用的是无效端口,当转换到主机IP,性能问题!
            ip地址[] AddressList中= Dns.GetHostAddresses(主机名2);

            的foreach(ip地址theaddress在AddressList中)
            {
                //尝试创建套接字,并连接到主机上的指定端口
                TcpClient的TCP =新System.Net.Sockets.TcpClient();
                尝试
                {
                    tcP.ReceiveTimeout = 1;
                    tcP.SendTimeout = 1;
                    tcP.Connect(theaddress,portno1);
                    displayGreen1();
                    tcP.Close();
                }
                抓住
                {
                    displayRed1();
                }
            }

        }

//改变灯当满足条件

        公共无效displayGreen1()
        {
            pictureBox2.Visible = FALSE;
            pictureBox1.Visible =真;
        }

        私人无效displayRed1()
        {
            pictureBox2.Visible =真;
            pictureBox1.Visible = FALSE;
        }
 

解决方案 十五 多线程 上

这是发生,因为UI控件只能从UI线程进行更新。当你的不的创建一个新的线程,code的更新控件运行在UI线程上,所以它可以作为你的期望。当你的执行的创建一个新的线程,因为这个线程的不是的UI线程,在code这是应该更新控件不这样做。

您可以确保通过更改方法是,code的更新控制UI线程上运行呼吁: -

  this.BeginInvoke(新动作(()=> displayRed1()));
 

  this.BeginInvoke(新动作(()=> displayGreen1()));
 

顺便说一句(无关您当前的问题): -

尽量避免创建一个明确的线索。而是使用线程池来管理线程对你来说,如 ThreadPool.QueueUserWorkItem(X => InitChecks())。 (请注意,这仍然会在非UI线程中运行,所以你仍然需要使用的BeginInvoke()详见上文)。线程池最清楚什么时候创建并执行一个线程,并使用它,最终,让你的code更有效。

尽量避免受凉的在尝试{...}赶上{...}所有的异常类型。这说明你的code知道该怎么办时的任意的异常类型被抛出。相反,只能赶你确切地知道如何处理,

例外

例如。

 尝试
{
    ...
}
赶上(TcpException)
{
    ...
}
赶上(AnotherKnownException)
{
    ...
}
...
 

请注意,这是确定也有一个块的所有的异常类型,只要你退出该块时重新抛出异常,

例如。

 尝试
{
    ...
}
赶上(KnownException)
{
    ...
}
赶上(例外)
{
    //执行一些日志,回滚段等。
    扔;
}
 

With some help I have managed to create a new thread, although the method appears to execute, the conditions of the method either make a green or red light appear, although when running the method (Check1..etc) without the new thread the changes are reflected on the GUI (e.g. Red / Green Light Appears), but when creating a new thread and running the method the changes are not reflected on the Form / 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;
        }

解决方案

This is happening because UI controls can only be updated from the UI thread. When you do not create a new thread, the code which updates the controls runs on the UI thread, so it works as you expect. When you do create a new thread, because this thread is not the UI thread, the code which is supposed to update the controls fails to do so.

You can ensure that the code which updates the controls runs on the UI thread by changing the method calls to:-

this.BeginInvoke(new Action(() => displayRed1()));

and

this.BeginInvoke(new Action(() => displayGreen1()));

Incidentally (unrelated to your current problem):-

Try to avoid creating an explicit thread. Instead use the thread pool to manage the thread for you, e.g. ThreadPool.QueueUserWorkItem(x => InitChecks()). (Note that this will still run on a non-UI thread so you still need to use BeginInvoke() as detailed above.). The thread pool knows best about when to create and execute a thread and using it will, ultimately, make your code more efficient.

Try to avoid catching all exception types in your try{...}catch{...}. This is stating that your code knows what to do when any type of exception is thrown. Instead, only catch exceptions which you know exactly how to handle,

e.g.

try
{
    ...
}
catch(TcpException)
{
    ...
}
catch(AnotherKnownException)
{
    ...
}
...

Note that it is OK to also have a catch block for all exception types as long as you rethrow the exception when exiting the block,

e.g.

try
{
    ...
}
catch(KnownException)
{
    ...
}
catch(Exception)
{
    // perform some logging, rollback, etc.
    throw;
}