【问题标题】:Using ThreadStart my UI stuck使用 ThreadStart 我的 UI 卡住了
【发布时间】:2013-04-20 07:47:36
【问题描述】:

我是线程新手 我的用户界面在流程完成之前没有响应。谁能告诉我这里出了什么问题。

精简代码:

  static string replacedname = "", replacedwith;
            private void startProcess(string FPath, string RNo)
            {
                if (FPath != "" && RNo != "")
                {
                    ....

                    UnZip(FPath, Path.GetDirectoryName(FPath) + "\\" + replacedwith);

                    DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(FPath) + "\\" + replacedwith);
                    foreach (FileInfo File1 in dir.GetFiles("*.zip"))
                    {
                        UnZip(File1.FullName, Path.GetDirectoryName(File1.FullName));
                        File.Delete(File1.FullName);
                    }

                }

                replacedname = "";
                MessageBox.Show("Completed");

            }
            private void button1_Click(object sender, EventArgs e)
            {

                ThreadStart threadStart = delegate() { startProcess(textBox1.Text, textBox2.Text); };

                threadStart.BeginInvoke(null, null);


            }
            private void UnZip(string zipToExtract, string unzipDirectoryl) // Extract zip/lot file in same directory
            {

                if (this.progressBar1.InvokeRequired)
                {
                    progressBar1.Invoke(new Action(delegate() { UnZip(zipToExtract, unzipDirectoryl); }));

                }
                else if (this.label3.InvokeRequired)
                {
                    label3.Invoke(new Action(delegate() { UnZip(zipToExtract, unzipDirectoryl); }));
                }
                else
                {                        ....
                            progressBar1.Value += 1;
                            progressBar1.Refresh();
                            label3.Text = ((progressBar1.Value * 100) / (progressBar1.Maximum)).ToString();
                            label3.Refresh();
                        ...
                }
            }


            private void status(string msg, Color selcColor)
            {
                if (this.richTextBox1.InvokeRequired)
                {
                    richTextBox1.Invoke(new Action(delegate() { status(msg, selcColor); }));
                }
                else
                {
                    richTextBox1.SelectionStart = richTextBox1.Text.Length;
                    var oldcolor = richTextBox1.SelectionColor;

                    richTextBox1.SelectionColor = selcColor;
                    richTextBox1.AppendText(msg + "\n");
                    richTextBox1.SelectionColor = oldcolor;
                    richTextBox1.Refresh();
                    richTextBox1.ScrollToCaret();
                }
            }

【问题讨论】:

  • a) 代码太多了。
  • b) 尝试用 Control.BeginInvoke 替换 Control.Invoke
  • 这里的代码太多了,反正本站不适合“调试我的代码”
  • @HenkHolterman 如果我使用 Begin-invoke 它在另一个线程中工作。我需要按顺序工作

标签: c# multithreading user-interface


【解决方案1】:

替换你的代码

 private void button1_Click(object sender, EventArgs e)
        {
            ThreadStart threadStart = delegate() { startProcess(textBox1.Text, textBox2.Text); };
            threadStart.BeginInvoke(null, null);
        }

 private void button1_Click(object sender, EventArgs e)
        {
            ThreadStart threadStart = delegate() { startProcess(textBox1.Text, textBox2.Text); };
            Thread thread = new Thread(threadStart);
            thread.Start();
        }

这将使用您分配的委托启动一个新线程。
有关 MSDN 参考,请参阅 here

编辑

在您的UnZip-方法中,您正在做一些奇怪的事情

private void UnZip(string zipToExtract, string unzipDirectoryl){

            if (this.progressBar1.InvokeRequired)
            {
                progressBar1.Invoke(new Action(delegate() { UnZip(zipToExtract, unzipDirectoryl); }));

            }
            else if (this.label3.InvokeRequired) // why else if on another control???
            {
                label3.Invoke(new Action(delegate() { UnZip(zipToExtract, unzipDirectoryl); }));
            }
            else
            {                        ....
                        progressBar1.Value += 1;
                        progressBar1.Refresh(); //why use Refresh()?
                        label3.Text = ((progressBar1.Value * 100) / (progressBar1.Maximum)).ToString();
                        label3.Refresh();
                    ...
            }
        }

您不能调用progressbar1.InvokeRequired,如果它返回错误,请在标签控件上使用else if! 您必须为每个控件使用单独的 if/else

if (this.progressBar1.InvokeRequired)
     progressBar1.Invoke(new Action(delegate() { progressbar1.Value++; }));
else 
     progressbar1.Value++; //pseudo-code 

【讨论】:

  • 它仍然和以前一样。两者都在执行,但我的 UI 在很长一段时间内没有响应
  • 所有... 我不知道你所有的代码。不过,这是一种奇怪的行为!
【解决方案2】:

您应该在 WinForms 中使用 BackgroundWorker 控件进行异步操作。使用详情和示例请参考thisMSDN 文章。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    • 2018-04-22
    • 1970-01-01
    • 2015-01-16
    • 2023-02-09
    相关资源
    最近更新 更多