您的代码存在几个问题:
1:你几乎不想打电话Thread.Abort
- 这样做可能会产生不可预测的影响,特别是当一个线程终止另一个线程时。请参阅 MSDN 了解更多信息。 http://msdn.microsoft.com/en-us/library/5b50fdsz%28v=vs.100%29.aspx
关闭线程的正确方法是使用某种消息告诉线程自行退出 - 设置静态变量(线程定期检查)、使用同步对象等。Thread.Abort()
是一个很大的禁忌。
2:你的逻辑倒退了:你在主线程上进行了耗时的操作(按钮单击事件处理程序显示这是你的主 UI 线程),并且你试图从后台线程显示进度对话框。
应该是相反的:您应该在单击处理程序内设置用于后台处理的所有数据,显示进度对话框(假设它是无模式的),然后启动将执行处理的后台线程。
在处理过程中,后台线程应该不断向进度窗口通知其进度,一旦完成,它还应该向进度窗口通知这一事实。
每当您需要通知 UI 线程时,您都必须正确地将调用编组到正确的线程。这是因为任何 UI 元素只能从创建它的线程访问 - 例如,如果不封送调用,则无法从工作线程设置标签控件的文本。
你需要使用InvokeRequired http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx / BeginInvoke() http://msdn.microsoft.com/en-us/library/system.windows.forms.control.begininvoke.aspx用于编组。打电话时BeginInvoke()
你将通过一名代表;像这样的东西(抱歉 C# 语法,我不太熟悉 VB.NET - 应该很容易移植它):
private void SomeEventHandler ( object oSender, EventArgs oE )
{
if ( InvokeRequired )
{
MethodInvoker oDelegate = (MethodInvoker) delegate
{
SomeEventHandler ( oSender, oE );
};
BeginInvoke ( oDelegate );
return;
}
else
{
// already on the correct thread; access UI controls here
}
}
所有这一切都是因为控件通过消息处理许多属性更新,并且这些消息必须以正确的顺序同步传递。确保这一点的唯一方法(无需一些非常复杂的编码)是在线程运行消息泵的同一线程上创建所有控件。
See 这个问题 https://stackoverflow.com/questions/2073076/c-sharp-winforms-possible-to-construct-form-on-background-thread-then-display有关在主 UI 线程以外的线程上创建 UI 的更多信息。 (这是可能的,但你只想这样做,如果你真的真的需要那个。这种情况相当罕见。)