我有一个登录表单显示在主表单之前,使用Program.cs中的代码:
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += Unhandled;
frmLogin loginForm;
using (loginForm = new frmLogin())
{
if (loginForm.ShowDialog() == DialogResult.OK)
{
NRBQConsts.userName = loginForm.UserName;
NRBQConsts.pwd = loginForm.Password;
NRBQConsts.currentSiteNum = loginForm.SiteNumber;
}
else
{
Application.Exit(); // klang!
}
}
Application.Run(new frmMain());
}
static void Unhandled(object sender, UnhandledExceptionEventArgs exArgs)
{
ExceptionLoggingService.Instance.WriteLog(String.Format("From
application-wide exception handler: {0}", exArgs.ExceptionObject));
}
如果用户选择"关闭"按钮(而不是尝试登录),登录表单应该关闭,主窗体不应该显示,应用程序应该关闭。如果用户选择" OK"按钮,登录表单应该关闭,然后应该显示主表单。
选择"关闭"会发生什么?按钮导致应用程序与clangy,Gong Show-esque"崩溃"崩溃声音。我的日志文件中有这个异常消息:
日期:2009/9/9 8:57:51 PM 消息:已到达frmLogin.buttonOK_Click 日期:2009年4月9日8:57:51 PM 消息:来自应用程序范围的异常处理程序:System.NullReferenceException:NullReferenceException 在NRBQ.frmLogin.GetSiteNum() 在NRBQ.frmLogin.buttonOK_Click(对象发件人,EventArgs e) 在System.Windows.Forms.Control.OnClick(EventArgs e) 在System.Windows.Forms.Button.OnClick(EventArgs e) 在System.Windows.Forms.ButtonBase.WnProc(WM wm,Int32 wParam,Int32 lParam) 在System.Windows.Forms.Control._InternalWnProc(WM wm,Int32 wParam,Int32 lParam) 在Microsoft.AGL.Forms.EVL.EnterModalDialog(IntPtr hwnModal) 在System.Windows.Forms.Form.ShowDialog() 在NRBQ.Program.Main()
以下是登录表单中的相关代码:
public partial class frmLogin : Form
{
public string UserName { get { return textBoxUsername.Text; } }
public string Password { get { return textBoxPwd.Text; } }
public string SiteNumber { get { return GetSiteNum(); } }
private string GetSiteNum()
{
String candidateSiteNum =
listBoxSitesWithFetchedData.SelectedItem.ToString();
if (String.IsNullOrEmpty(candidateSiteNum))
{
candidateSiteNum = "42"; // TODO: Remove before deploying
}
return candidateSiteNum;
}
public frmLogin()
{
InitializeComponent();
}
private void buttonClose_Click(object sender, EventArgs e)
{
ExceptionLoggingService.Instance.WriteLog("Reached
frmLogin.buttonClose_Click");
}
private void buttonOK_Click(object sender, EventArgs e)
{
ExceptionLoggingService.Instance.WriteLog("Reached
frmLogin.buttonOK_Click");
if (SanityCheck())
{
this.Close(); // closing this login form should make the main
form active/visible
}
else
{
MessageBox.Show("You have not yet provided some key data; be
sure to enter a username and a password");
}
}
private bool SanityCheck()
{
// For now, anyway, no site has to be selected; if none, use "42" by
default
return ((!(String.IsNullOrEmpty(textBoxUsername.Text.Trim())))
&& (!(String.IsNullOrEmpty(textBoxPwd.Text.Trim()))));
}
注意:" OK"按钮的DialogResult设置为" OK&#34 ;; "关闭"按钮的DialogResult设置为"取消"
为什么Application.Exit()会导致应用崩溃?什么是更友善,更温和的终止应用程序的方式?
为什么选择Okay按钮不允许主窗体随后显示?登录表单 关闭,即使选择了确定按钮(如果通过健全性检查),但是全部......主窗体不显示。
我根据下面的答案修改了我的代码,现在取消工作正常(关闭应用程序没有klang /崩溃),但是在选择"之后我仍然没有看到我的主要表单。行"登录表单上的按钮,即使我在登录表单代码中以编程方式将DialogResult设置为OK。
下面的相关代码。
Program.cs的
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += Unhandled;
frmLogin loginForm;
using (loginForm = new frmLogin())
{
if (loginForm.ShowDialog() == DialogResult.OK)
{
HHSConsts.userName = loginForm.UserName;
HHSConsts.pwd = loginForm.Password;
HHSConsts.currentSiteNum = loginForm.SiteNumber;
// TODO: Verify that these vals are valid
Application.Run(new frmMain());
}
}
}
FRMLOGIN.CS
private void buttonClose_Click(object sender, EventArgs e)
{
ExceptionLoggingService.Instance.WriteLog("Reached
frmLogin.buttonClose_Click");
this.DialogResult = DialogResult.Cancel; // <= necessary?
this.Close();
}
private void buttonOK_Click(object sender, EventArgs e)
{
ExceptionLoggingService.Instance.WriteLog("Reached
frmLogin.buttonOK_Click");
this.DialogResult = DialogResult.OK;
if (SanityCheck())
{
this.Close();
}
else
{
MessageBox.Show("You have not yet provided some key data; be
sure to enter a username and a password");
}
}
这是我在日志文件中看到的内容:
日期:2009/9/9 9:56:47 PM 消息:已到达frmLogin.buttonOK_Click 日期:2009年4月9日下午9:56:48 消息:来自应用程序范围的异常处理程序:System.NullReferenceException:NullReferenceException 在HHS.frmLogin.GetSiteNum() 在HHS.frmLogin.get_SiteNumber() 在HHS.Program.Main()
Merle Haggard演唱,&#34; 现在它又回到了密码室...... &#34;
我在GetSiteNum()中添加了一个消息框:
private string GetSiteNum()
{
ExceptionLoggingService.Instance.WriteLog("Reached
frmLogin.GetSiteNum()");
String candidateSiteNum =
listBoxSitesWithFetchedData.SelectedItem.ToString();
// TODO: Remove after testing
MessageBox.Show(String.Format("candidateSiteNum = {0}",
candidateSiteNum));
if (String.IsNullOrEmpty(candidateSiteNum))
{
candidateSiteNum = "03"; // TODO: Remove before deploying
}
return candidateSiteNum;
}
......而且我没有看到它,所以它已经爆发了:
String candidateSiteNum = listBoxSitesWithFetchedData.SelectedItem.ToString();
...选择&#34; OK&#34;此登录表单上的按钮。
答案 0 :(得分:2)
这是docs对Application.Exit
所说的内容:
通知所有消息泵必须终止,然后在处理完消息后关闭所有应用程序窗口。
这意味着它将启动一个很好的受控关闭 - 而不是立即退出,导致您的代码继续Application.Run
,这显然会崩溃并烧毁。
一种选择是使用Environment.Exit
代替,它将立即终止,但它是一个混乱的解决方案。另一种选择是在return
之后立即Application.Exit
,因此您永远不会到达Application.Run
。但是,仍然不是很好。
而只是尝试:
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += Unhandled;
frmLogin loginForm;
using (loginForm = new frmLogin())
{
if (loginForm.ShowDialog() == DialogResult.OK)
{
NRBQConsts.userName = loginForm.UserName;
NRBQConsts.pwd = loginForm.Password;
NRBQConsts.currentSiteNum = loginForm.SiteNumber;
Application.Run(new frmMain());
}
}
}
从Main
返回也将退出应用程序,因此不需要任何其他内容。
编辑:显然这不是你遇到的问题,但无论如何,这回答了标题中的问题。
答案 1 :(得分:2)
请勿针对您的登录表单致电Close()
,只需设置DialogResult
,如下所示。另请注意,在{ DialogResult.OK
告诉我们好的时候,之后我才设置SanityCheck()
:
private void buttonClose_Click(object sender, EventArgs e)
{
ExceptionLoggingService.Instance.WriteLog("Reached frmLogin.buttonClose_Click");
this.DialogResult = DialogResult.Cancel;
}
private void buttonOK_Click(object sender, EventArgs e)
{
ExceptionLoggingService.Instance.WriteLog("Reached frmLogin.buttonOK_Click");
if (SanityCheck())
{
this.DialogResult = DialogResult.OK;
}
}
您还应该确保在SanityCheck()
函数中选择了ListBox中的项目:
private bool SanityCheck()
{
if (listBoxSitesWithFetchedData.SelectedIndex == -1)
{
MessageBox.Show("You must select a site first!");
return false;
}
bool pass = ((!(String.IsNullOrEmpty(textBoxUsername.Text.Trim())))
&& (!(String.IsNullOrEmpty(textBoxPwd.Text.Trim()))));
if (!pass)
{
MessageBox.Show("You have not yet provided some key data; be sure to enter a username and a password");
}
return pass;
}
答案 2 :(得分:1)
看起来您从未在“确定”按钮中设置“对话”结果。
设置对话框结果如下:
this.DialogResult = DialogResult.OK;
在您进行完整性检查后,在this.Close()
解决问题之前,因为错误是由Null reff引起的。
您还需要在表单返回的其他位置设置取消的结果(或者我倾向于在表单加载时,假设失败,直到您知道它成功并返回。)