C#线程和ShowDialog问题

发布于 2024-11-09 17:05:20 字数 5496 浏览 0 评论 0原文

ProgressForm类:

public partial class ProgressForm : Form
    {
        public int prc = 0, sz;
        MainForm mf;

        public ProgressForm(MainForm MF)
        {
            InitializeComponent();
            mf = MF;
            sz = 0;
        }

        public ProgressForm(int mx)
        {
            InitializeComponent();
            sz = mx;
        }

        public void SetMax(int mx)
        {
            sz = mx;
        }

        public void StartProgress()
        {
            timer1.Enabled = true;
        }

        public void IncProgress(int prg)
        {
            prc += prg;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            double pos = (double)prc / (double)sz * 100;
            progressBar.Value = (int)pos;
        }

        private void ProgressForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            timer1.Enabled = false;
        }

        private void cancelBtn_Click(object sender, EventArgs e)
        {
            mf.isCanceled = true;
            this.Close();
        }

        private void ProgressForm_Shown(object sender, EventArgs e)
        {
            progressBar.Value = 0;
            StartProgress();
        }

    }

MainForm类:

void DeleteFiles()
            {
                int x = 0;
                int cnt = resultList.Count;
                isCanceled = false;

                DeleteThreadHandler("beginprogress");
                try
                {
                    DeleteThreadHandler("begindelete");
                    for (int j = 0; j < cnt; j++)
                    {
                        if (resultList[x].isChecked)
                        {
                            DeleteThreadHandler("progress");
                            DeleteFile(resultList[x].name, deleteForm.isDeletePermanently);
                            if (File.Exists(resultList[x].name))
                            {
                                DeleteErrorHandler(resultList[x].name);
                                isError = true;
                            }
                            else
                                resultList.RemoveAt(x);
                        }
                        else
                            ++x;

                        if (isCanceled)
                            break;
                    }
                }
                finally
                {
                    validity(true);
                    DeleteThreadHandler("enddelete");
                }
            }

            void DeleteErrorHandler(string val)
            {
                Action action = null;

                action = () =>
                {
                    errorReportForm.AddError(val);
                };

                this.BeginInvoke(action);
            }

            void DeleteThreadHandler(String title)
            {
                Action action = null;
                if (title == "beginprogress")
                {
                    action = () =>
                    {

                    };
                }
                else
                if (title == "begindelete")
                {
                    action = () =>
                    {
                        olvVirtual.BeginUpdate();
                    };
                }
                else
                    if (title == "enddelete")
                    {
                        action = () =>
                        {
                            olvVirtual.VirtualListSize = resultList.Count;
                            olvVirtual.EndUpdate();
                            RefreshStatus();
                            progressForm.Close();
                            if (isError)
                                errorReportForm.ShowDialog();
                        };
                    }
                if (title == "progress")
                {
                    action = () =>
                    {
                        progressForm.IncProgress(1);
                    };
                }

                this.BeginInvoke(action);
            }    


    private void DeleteBtn_Click(object sender, EventArgs e)
        {
            int checkedcount = GetCheckedCount();
            if (checkedcount == 0)
            {
                MessageBox.Show("Please mark at least a file first");
                return;
            }
            DialogResult dr = new DialogResult();
            if (deleteForm == null)
                deleteForm = new DeleteForm();
            dr = deleteForm.ShowDialog();
            if (dr == DialogResult.OK)
            {
                //if (progressForm == null)
                progressForm = new ProgressForm(this);
                progressForm.Text = "Deleting...";
                progressForm.SetMax(checkedcount);

                if (errorReportForm == null)
                    errorReportForm = new ErrorReportForm();
                errorReportForm.ClearMemo();
                isError = false;

                Thread t = new Thread(DeleteFiles);
                t.Start();
                progressForm.ShowDialog();
            }
        }

在progressForm中,有一个进度条和进度条。计时器每 500 毫秒更新一次进度。 问题是我仍然可以访问主窗体,我也尝试 BeginInvoke 但都不起作用 有人知道出了什么问题吗?

谢谢

编辑:我找到了这个混乱的根源,它是使用Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile的DeleteFile。用非托管代码替换它后,它工作正常。

ProgressForm Class:

public partial class ProgressForm : Form
    {
        public int prc = 0, sz;
        MainForm mf;

        public ProgressForm(MainForm MF)
        {
            InitializeComponent();
            mf = MF;
            sz = 0;
        }

        public ProgressForm(int mx)
        {
            InitializeComponent();
            sz = mx;
        }

        public void SetMax(int mx)
        {
            sz = mx;
        }

        public void StartProgress()
        {
            timer1.Enabled = true;
        }

        public void IncProgress(int prg)
        {
            prc += prg;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            double pos = (double)prc / (double)sz * 100;
            progressBar.Value = (int)pos;
        }

        private void ProgressForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            timer1.Enabled = false;
        }

        private void cancelBtn_Click(object sender, EventArgs e)
        {
            mf.isCanceled = true;
            this.Close();
        }

        private void ProgressForm_Shown(object sender, EventArgs e)
        {
            progressBar.Value = 0;
            StartProgress();
        }

    }

MainForm class:

void DeleteFiles()
            {
                int x = 0;
                int cnt = resultList.Count;
                isCanceled = false;

                DeleteThreadHandler("beginprogress");
                try
                {
                    DeleteThreadHandler("begindelete");
                    for (int j = 0; j < cnt; j++)
                    {
                        if (resultList[x].isChecked)
                        {
                            DeleteThreadHandler("progress");
                            DeleteFile(resultList[x].name, deleteForm.isDeletePermanently);
                            if (File.Exists(resultList[x].name))
                            {
                                DeleteErrorHandler(resultList[x].name);
                                isError = true;
                            }
                            else
                                resultList.RemoveAt(x);
                        }
                        else
                            ++x;

                        if (isCanceled)
                            break;
                    }
                }
                finally
                {
                    validity(true);
                    DeleteThreadHandler("enddelete");
                }
            }

            void DeleteErrorHandler(string val)
            {
                Action action = null;

                action = () =>
                {
                    errorReportForm.AddError(val);
                };

                this.BeginInvoke(action);
            }

            void DeleteThreadHandler(String title)
            {
                Action action = null;
                if (title == "beginprogress")
                {
                    action = () =>
                    {

                    };
                }
                else
                if (title == "begindelete")
                {
                    action = () =>
                    {
                        olvVirtual.BeginUpdate();
                    };
                }
                else
                    if (title == "enddelete")
                    {
                        action = () =>
                        {
                            olvVirtual.VirtualListSize = resultList.Count;
                            olvVirtual.EndUpdate();
                            RefreshStatus();
                            progressForm.Close();
                            if (isError)
                                errorReportForm.ShowDialog();
                        };
                    }
                if (title == "progress")
                {
                    action = () =>
                    {
                        progressForm.IncProgress(1);
                    };
                }

                this.BeginInvoke(action);
            }    


    private void DeleteBtn_Click(object sender, EventArgs e)
        {
            int checkedcount = GetCheckedCount();
            if (checkedcount == 0)
            {
                MessageBox.Show("Please mark at least a file first");
                return;
            }
            DialogResult dr = new DialogResult();
            if (deleteForm == null)
                deleteForm = new DeleteForm();
            dr = deleteForm.ShowDialog();
            if (dr == DialogResult.OK)
            {
                //if (progressForm == null)
                progressForm = new ProgressForm(this);
                progressForm.Text = "Deleting...";
                progressForm.SetMax(checkedcount);

                if (errorReportForm == null)
                    errorReportForm = new ErrorReportForm();
                errorReportForm.ClearMemo();
                isError = false;

                Thread t = new Thread(DeleteFiles);
                t.Start();
                progressForm.ShowDialog();
            }
        }

In progressForm, there are a progress bar & timer which update the progress every 500 ms.
The problem is I still can access the main form, I also try BeginInvoke but neither works
Anyone know what is wrong ?

Thanks

EDITED: I've found source of this mess, it's DeleteFile which use Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile. After replaced it with unmanaged code it works fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

画离情绘悲伤 2024-11-16 17:05:20

尝试

 progressForm.ShowDialog(this);  // assuming this is the main form

Try

 progressForm.ShowDialog(this);  // assuming this is the main form
栖迟 2024-11-16 17:05:20

很难确切地说出其原因是什么,但是通过一些调试您将有更好的机会发现原因。

我会尝试以下操作;

  • 当您在DeleteForm上运行ShowDialog时,这是否表现为DeleteForm的模式对话框,或者当DeleteForm可见时您仍然可以单击基础表单吗?如果没有,那么当您运行 ShowDialog(this) 时会吗?

  • 调用progressForm.ShowDialog(this)并设置几个断点(1)在DeleteFiles的开头和(2)在progressForm.IncProgress(1)行;当断点被击中时,使用立即窗口检查progressForm.Owner和progressForm.Modal

另外,您将对当前对象的引用传递到进度表单中的目的是什么? ProgressForm 的构造函数中是否有任何内容可能导致这些问题?

MSDN 中关于模态对话框的另一件事需要注意的是“关闭”按钮的使用。
以下内容来自;
http://msdn.microsoft.com/en-us/library/w61zzfwe.aspx

当表单显示为模式时
对话框,单击“关闭”按钮
(带有 X 的按钮
表格右上角)原因
要隐藏的表格和
DialogResult 属性设置为
DialogResult.Cancel。与无模式不同
表单时,不会调用 Close 方法
当用户通过 .NET Framework
单击 a 的关闭表单按钮
对话框或设置值
DialogResult 属性。相反,
表单已隐藏,可以再次显示
无需创建新实例
对话框。因为显示了一个表格
因为对话框被隐藏而不是
已关闭,您必须调用 Dispose
当表单为 no 时表单的方法
您的应用程序需要的时间更长。

It's hard to say exactly what the cause of this is, but you'll have a better chance of discovering the cause with a bit of debugging.

I would try the following;

  • When you run ShowDialog on DeleteForm, does this behave as a modal dialog for DeleteForm or can you still click the underlying form while DeleteForm is visible? If not, does it when you run ShowDialog(this)?

  • Call progressForm.ShowDialog(this) and set a couple of breakpoints (1) at the beginning of DeleteFiles and (2) at line progressForm.IncProgress(1); When the breakpoints are hit, use the immediate window to check progressForm.Owner and progressForm.Modal

Also, what are you passing a reference to the current object into progress form for? Is there anything in the constructor of ProgressForm that could cause these issues?

Another thing to note on Modal Dialogs from MSDN is the use of the Close button.
The following comes from;
http://msdn.microsoft.com/en-us/library/w61zzfwe.aspx

When a form is displayed as a modal
dialog box, clicking the Close button
(the button with an X at the
upper-right corner of the form) causes
the form to be hidden and the
DialogResult property to be set to
DialogResult.Cancel. Unlike modeless
forms, the Close method is not called
by the .NET Framework when the user
clicks the close form button of a
dialog box or sets the value of the
DialogResult property. Instead the
form is hidden and can be shown again
without creating a new instance of the
dialog box. Because a form displayed
as a dialog box is hidden instead of
closed, you must call the Dispose
method of the form when the form is no
longer needed by your application.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文