C#线程和ShowDialog问题
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尝试
Try
很难确切地说出其原因是什么,但是通过一些调试您将有更好的机会发现原因。
我会尝试以下操作;
当您在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
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