我有一个 C# WinForms 应用程序。
我正在使用 Unity Container nuget 包来注入(inject)我的服务类。如果我在 Program.cs
中获取服务类并调用我的 Web api 以使用 odata 验证用户名和密码,则它会成功运行。如果我调用 Application.Run(myForm)
(其中 myForm
是 Telerik RadForm),并异步运行相同的调用,则应用程序将关闭,不会引发任何异常。
我正在使用 Application.ThreadException
并注册 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException)
但这不会捕获任何内容。
导致应用程序崩溃的行是对 System.Net.Http.HttpClient.PostAsync() 的调用。此调用是从位于单独的 .Net Standard 2.0 类库
中的服务类内部进行的。主应用程序是 .NET Framework 4.7.2 Windows 应用程序
,UI 控件位于 .NET Framework 4.7.2 类库
中。同样,如果在 Telerik RadForm 外部调用,则此调用会成功。
在 Telerik RadForm 中,我尝试使用以下命令执行调用:
private async void btnLogin_Click(object sender, System.EventArgs e)
var t = new Thread(() => Runner.DoWork(new Credentials(u, p, CLIENT_ID)))
- 不使用
await
异步调用静态方法
当我在服务类上调用 LoginAsync(...).Result
时,我确实得到了不同的结果。这导致应用程序进入线程锁定状态,但并没有使应用程序崩溃。
更新:
有两个 RadForm;一个 DashboardForm
和一个 LoginForm
。 Program.cs
启动仪表板来检查现有的承载 token 。如果 token 不存在,仪表板将使用 .ShowDialog()
显示登录信息,以防止在经过身份验证之前使用仪表板。然后登录使用上面描述的服务类。
如果我不是使用 Application.Run()
在 Program.cs
中启动仪表板而是启动登录,则用于身份验证的服务调用会成功。
然后,我尝试在新线程中从仪表板启动登录,但这导致了与上述相同的问题。
如果从另一个表单显示的表单调用 System.Net.Http.HttpClient.PostAsync()
,为什么应用程序会崩溃(无一异常(exception))?
计划
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
WinInjectionHelper.Register(UnityConfig.RegisterComponents);
Application.ThreadException += Application_ThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.Run(new DashboardForm());
}
private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
MessageBox.Show("Big error...");
}
仪表板
public partial class DashboardForm : Telerik.WinControls.UI.RadForm, IDashboard
{
private readonly IProductService _service;
public DashboardForm()
{
this._service = WinInjectionHelper.Generate2<IProductService>();
this.InitializeComponent();
}
private void DashboardForm_Load(object sender, EventArgs e)
{
if (this.NotAuthenticated())
{
var frm = new LoginForm();
if (frm.ShowDialog() != DialogResult.OK)
{
this.Close();
}
}
else
{
//TODO: display error to user
this.Close();
}
}
}
登录
public partial class LoginForm : Telerik.WinControls.UI.RadForm
{
private const string CLIENT_ID = "...";
private readonly IAuthenticationService _service;
public LoginForm()
{
this._service = WinInjectionHelper.Generate2<IAuthenticationService>();
this.InitializeComponent();
}
private void btnCancel_Click(object sender, System.EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
private async void btnLogin_Click(object sender, System.EventArgs e)
{
var u = this.txtUsername.Text.Trim();
var p = this.txtPassword.Text.Trim();
if (string.IsNullOrWhiteSpace(u))
{
MessageBox.Show("Username is required!", "NOTICE", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
if (string.IsNullOrWhiteSpace(p))
{
MessageBox.Show("Password is required!", "NOTICE", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
try
{
var jwt = await this._service.LoginAsync(new Credentials(u, p, CLIENT_ID));
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, u),
new Claim(ClaimTypes.Email, u),
new Claim(ClaimTypes2.AccessToken, jwt.AccessToken),
}, "JWT");
((GenericPrincipal)Thread.CurrentPrincipal).AddIdentity(identity);
this.DialogResult = DialogResult.OK;
this.Close();
}
catch
{
MessageBox.Show("An error occurred while processing your request.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
最佳答案
您可以检查 Windows 事件查看器并在应用程序下查找崩溃日志。我正在开发的一个应用程序也遇到了同样的问题,这是唯一有相关信息的地方。它实际上帮助我解决了与针对特定 .NET Framework 版本相关的问题。单击左下角的窗口按钮,然后在其中输入“事件查看器”,然后单击显示的图标。
最简单的方法是运行应用程序并让它崩溃,然后立即转到事件查看器,这样它将位于列表的顶部。
关于C# WinForms 崩溃,没有异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57062876/