井右寺 发表于 2019-8-12 13:43

c#桌面编程combobox导致子线程变慢

今天遇到一个奇葩情况,
c#的桌面编程,有一个动作,获取combobox的值传递给子线程,子线程在开子进程调用外部exe并同步输出
只要把combobox的值往里面传递,子线程的执行效率就会大幅降低
不传递使用combobox的值时,子线程执行用时2s左右,传递并使用combobox后,用时20s接近30
奇葩,本人不会c#,猜测是不是引用传递到子线程的时候,引起了不必要的更新?
有没有大佬知道是个什么情况?
感激不尽!

goldli 发表于 2019-8-12 14:27

看情况应该是从子线程里直接取了combobox的值。
你可以从主线程里取值再传递给子线程。这样就好了。

wtujoxk 发表于 2019-8-12 14:39

C#子线程和控件交互,最好用委托或事件。

井右寺 发表于 2019-8-12 14:45

goldli 发表于 2019-8-12 14:27
看情况应该是从子线程里直接取了combobox的值。
你可以从主线程里取值再传递给子线程。这样就好了。

{:1_924:}有这个怀疑
其实取值就是在主线程完成的,拼接别的字符串后传递给子线程的
因为自己并不会c#,所以不太清楚,字符串拼接,是值传递还是引用传递?
测试了把传进去的clone之后仍然影响效率
感觉这个时候应该已经是值传递了,有点迷

井右寺 发表于 2019-8-12 14:51

wtujoxk 发表于 2019-8-12 14:39
C#子线程和控件交互,最好用委托或事件。

子线程用了委托和界面进行交互,仍然不行
屏蔽子线程内部所有和界面交互的代码,效率依然受影响
相当于子线程现在完全是独立的和外部无交互的状态,唯一可能存在的就是combobox的值被引用传递进来了,但是也只有获取动作,没有别的动作。
就感觉这个问题很奇葩,
在主线程获取combobox的值,拼接后传给进子线程,和不传给子线程,完全是两个效率

wtujoxk 发表于 2019-8-12 15:10

井右寺 发表于 2019-8-12 14:51
子线程用了委托和界面进行交互,仍然不行
屏蔽子线程内部所有和界面交互的代码,效率依然受影响
相当于 ...

上代码或者工程!

井右寺 发表于 2019-8-12 15:36

wtujoxk 发表于 2019-8-12 15:10
上代码或者工程!

嗯,因为是客户代码,所以不太方便,截取部分做伪代码吧
    public partial class Form1 : Form
    {
      public delegate void UpdateUI();
      UpdateUI updateUI;

      private void button1_Click(object sender, EventArgs e)
      {
            string command = cbx.SelectedItem.ToString() + " " + tbx4.Text.Trim();
            StartCMD1(command);
            updateUI = delegate
            {
                tbx4.Text = "";

            };
            tbx4.Invoke(updateUI);
            tbx4.Focus();
      }
      public void StartCMD1(string command)
      {
            Thread thread = new Thread(new ParameterizedThreadStart(CallExe));
            thread.Start(command);//开始线程
      }
      public void CallExe(object command)
      {
            Process p = new Process();
            try
            {
                //command
                //要执行进程的名称
                p.StartInfo.FileName = System.Environment.CurrentDirectory + "\\client\\" + "homekit_download_client.exe";
                p.StartInfo.Arguments = command.ToString();
                // MessageBox.Show(command.ToString());
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.WorkingDirectory = System.Environment.CurrentDirectory + "\\client";
                //可能接受來自調用程序的輸入信息
                p.StartInfo.RedirectStandardInput = true;
                //由調用程序獲取輸出信息
                p.StartInfo.RedirectStandardOutput = true;
                //不顯示程序窗口
                p.StartInfo.CreateNoWindow = true;

                p.Start();//啟動程序

                p.StandardInput.AutoFlush = true;

                //获取CMD窗口的輸出信息:
                string sOutput = p.StandardOutput.ReadToEnd();
                updateUI = delegate
                {
                  tbx2.Text = sOutput + "\r\n";
                };
                tbx2.Invoke(updateUI);
                p.WaitForExit();//等待程序执行完退出进程
                p.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "提示");
            }
      }

    }
}

井右寺 发表于 2019-8-12 15:41

wtujoxk 发表于 2019-8-12 15:10
上代码或者工程!

{:1_887:}我也不太清楚正确性,麻烦大佬帮忙看看,可能存在的问题点
计时是callexe执行前后的时间差
之前试过,把取值放到selectchange里面赋值给外部变量,然后通过这个变量进行拼接,没效果
把callexe里面和外部交互的代码屏蔽,没有效果
就有点懵

wtujoxk 发表于 2019-8-12 16:17

本帖最后由 wtujoxk 于 2019-8-12 16:18 编辑

略改了一下,你自己测试看看!
    public partial class Form1 : Form
    {
      public Form1()
      {
            InitializeComponent();
      }

      private void Button1_Click(object sender, EventArgs e)
      {
            string command = cbx.SelectedItem.ToString() + " " + tbx4.Text.Trim();

            new Thread(delegate(){ CallExe(command); }).Start();

            UpdateUI(tbx4, "");
            tbx4.Focus();
      }
      public void CallExe(object command)
      {
            Process p = new Process();
            try
            {
                //command
                //要执行进程的名称
                p.StartInfo.FileName = System.Environment.CurrentDirectory + "\\client\\" + "homekit_download_client.exe";
                p.StartInfo.Arguments = command.ToString();
                // MessageBox.Show(command.ToString());
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.WorkingDirectory = System.Environment.CurrentDirectory + "\\client";
                //可能接受來自調用程序的輸入信息
                p.StartInfo.RedirectStandardInput = true;
                //由調用程序獲取輸出信息
                p.StartInfo.RedirectStandardOutput = true;
                //不顯示程序窗口
                p.StartInfo.CreateNoWindow = true;

                p.Start();//啟動程序

                p.StandardInput.AutoFlush = true;

                //获取CMD窗口的輸出信息:
                string sOutput = p.StandardOutput.ReadToEnd();

                UpdateUI(tbx2, sOutput + Environment.NewLine);

                p.WaitForExit();//等待程序执行完退出进程
                p.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "提示");
            }
      }
      private void UpdateUI(Control c, string content)
      {
            if (c.InvokeRequired)
                c.Invoke((EventHandler)delegate { c.Text = content; });
            else
                c.Text = content;
      }
    }

goldli 发表于 2019-8-13 15:42

new Thread(delegate(){ CallExe(command); }).Start();
改成用Task.Factory.StartNew(......)
页: [1]
查看完整版本: c#桌面编程combobox导致子线程变慢