- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我遇到了一个问题,我无法等待 FormClosing 事件中的异步函数,该函数将确定表单关闭是否应该继续。我创建了一个简单的示例,如果您关闭而不保存(很像记事本或 Microsoft Word),它会提示您保存未保存的更改。我遇到的问题是,当我等待异步保存函数时,它会在保存函数完成之前继续关闭表单,然后在完成后返回关闭函数并尝试继续。我唯一的解决方案是在调用 SaveAsync 之前取消关闭事件,然后如果保存成功它将调用 form.Close() 函数。我希望有一种更简洁的方法来处理这种情况。
要复制该场景,请创建一个带有文本框 (txtValue)、复选框 (cbFail) 和按钮 (btnSave) 的表单。这是表单的代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestZ
{
public partial class Form1 : Form
{
string cleanValue = "";
public Form1()
{
InitializeComponent();
}
public bool HasChanges()
{
return (txtValue.Text != cleanValue);
}
public void ResetChangeState()
{
cleanValue = txtValue.Text;
}
private async void btnSave_Click(object sender, EventArgs e)
{
//Save without immediate concern of the result
await SaveAsync();
}
private async Task<bool> SaveAsync()
{
this.Cursor = Cursors.WaitCursor;
btnSave.Enabled = false;
txtValue.Enabled = false;
cbFail.Enabled = false;
Task<bool> work = Task<bool>.Factory.StartNew(() =>
{
//Work to do on a background thread
System.Threading.Thread.Sleep(3000); //Pretend to work hard.
if (cbFail.Checked)
{
MessageBox.Show("Save Failed.");
return false;
}
else
{
//The value is saved into the database, mark current form state as "clean"
MessageBox.Show("Save Succeeded.");
ResetChangeState();
return true;
}
});
bool retval = await work;
btnSave.Enabled = true;
txtValue.Enabled = true;
cbFail.Enabled = true;
this.Cursor = Cursors.Default;
return retval;
}
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (HasChanges())
{
DialogResult result = MessageBox.Show("There are unsaved changes. Do you want to save before closing?", "Unsaved Changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (result == System.Windows.Forms.DialogResult.Yes)
{
//This is how I want to handle it - But it closes the form while it should be waiting for the Save() to complete.
//bool SaveSuccessful = await Save();
//if (!SaveSuccessful)
//{
// e.Cancel = true;
//}
//This is how I have to handle it:
e.Cancel = true;
bool SaveSuccessful = await SaveAsync();
if (SaveSuccessful)
{
this.Close();
}
}
else if (result == System.Windows.Forms.DialogResult.Cancel)
{
e.Cancel = true;
}
//If they hit "No", just close the form.
}
}
}
}
Edit 05/23/2013
Its understandable that people would ask me why I would be trying to do this. The data classes in our libraries will often have Save, Load, New, Delete functions that are designed to be run asynchronously (See SaveAsync as an example). I do not actually care that much about running the function asynchronously in the FormClosing Event specifically. But if the user wants to save before closing the form, I need it to wait and see if the save succeds or not. If the save fails, then I want it to cancel the form closing event. I'm just looking for the cleanest way to handle this.
最佳答案
在我看来,最好的答案是取消表单的关闭。总是。取消它,随心所欲地显示您的对话框,并在用户完成该对话框后,以编程方式关闭表单。
这是我的做法:
async void Window_Closing(object sender, CancelEventArgs args)
{
var w = (Window)sender;
var h = (ObjectViewModelHost)w.Content;
var v = h.ViewModel;
if (v != null &&
v.IsDirty)
{
args.Cancel = true;
w.IsEnabled = false;
// caller returns and window stays open
await Task.Yield();
var c = await interaction.ConfirmAsync(
"Close",
"You have unsaved changes in this window. If you exit they will be discarded.",
w);
if (c)
w.Close();
// doesn't matter if it's closed
w.IsEnabled = true;
}
}
请务必注意对 await Task.Yield()
的调用。如果被调用的异步方法总是异步执行,则没有必要。但是,如果该方法有任何同步路径(即 null 检查和返回等),Window_Closing 事件将永远不会完成执行并且对 w.Close()
的调用将抛出异常.
关于c# - 在 FormClosing 事件中等待异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16656523/
我正在开发一个 C# 应用我需要在用户关闭表单之前进行一些验证。 我尝试使用 FormClosing 事件,但没有成功,后来我用了FormClosed事件,但是一样。 问题是,当我单击“关闭按钮”(在
在 myForm_FormClosing 之后是否有任何机会调用 timer_Tick在下面的代码中。 如果有机会:在 myForm_FormClosing 中调用 timer.Stop() 是否足以
我有一个组合框来设置用户文化: 如果我更改 Culture 值 x 次,当用户尝试退出时,FormClosing 方法将被触发 x 次。 这是我的 FormClosing 事件: privat
我的电脑有一个备用电源,它与电脑和墙壁串联连接。当我从墙上拔下电源线时,备用电源会在 2-5 分钟后关闭计算机。正是在这段时间里,我想使用以下代码将数据写入文件: private void Form1
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我尝试调用 FormClose 方法,但尝试时其参数出现问题: FormName.FormClose(nil, CaFree); 通常,我可以使用 nil 或 sender as TOBject 来调
当 FormClosing 中抛出异常时,我无法使用正常的 try/catch 捕获它 - 为什么不呢? 例子: public partial class Form2 : Form {
我有两个表单并将它们链接起来,这样当第二个表单关闭时,第一个表单也会关闭(使用 FormClosing 方法)。 问题是,当我想隐藏第二个表单时,它会自动关闭第一个。有没有一种方法可以在不实际调用 F
我试图在关闭菜单表单时关闭我的应用程序。这是我的代码: private void frmMenu_FormClosing(object sender, FormClosingEventArgs e)
我从主窗体中打开了一个子窗体,如下所示: var cf = new ChildForm { Owner = this }; cf.Show(); 然后子窗体在另一个线程上进行一些绘制。 当用户试图关闭
我的主窗体上有一个 ToolStripButton 并附加了一个单击事件,单击它会打开一个对话框并将 toolStripButton 的 Checked 状态设置为“true”。在通过上述单击打开的窗
我想在程序中的 Form 关闭时收到通知,以便我可以保存其子控件的状态,然后在下次打开该窗体时恢复这些控件状态。我将用于保存控件状态的代码放在窗体的 FormClosing 方法中。但是,如果关闭主窗
我有一个 MainForm。我可以使用关闭按钮(右上角)或单击菜单项 miExit 来关闭它。 我的问题是当我单击 miExit 并回答“确定”时,它显示消息框 TWICE。我该如何解决? (我明白为
我有以下代码: private void form1_closing(object sender, FormClosingEventArgs e) { e.Cancel = true;
我有一个简单的基于表单的 .NET 应用程序。在此,我捕获 FormClosing 事件以防止关闭应用程序,而是将其最小化。该应用程序应始终打开。这是我使用的代码: private void Brow
我遇到了一个问题,我无法等待 FormClosing 事件中的异步函数,该函数将确定表单关闭是否应该继续。我创建了一个简单的示例,如果您关闭而不保存(很像记事本或 Microsoft Word),它会
我有一个简单的 Windows 窗体,它在运行时托管属性控件。当用户单击关闭 [X] 时,我希望保持窗口及其内容处于事件状态,而不是通过处理 FormClosing 事件、取消事件并简单地隐藏表单来杀
在 Delphi 7 中,我有一个 TMainForm.FormClose 过程,旨在在程序退出时写出一些状态。这在手动关闭程序时效果很好。但是,我发现如果程序被 Windows“强制”退出(例如在
这个问题可能看起来像重复,但我在测试我的程序时遇到了这个问题,我对你如何解决它感到有点困惑。 我有一个 winform,它有一个表单关闭事件。在这种情况下,我会弹出一个消息框,询问用户“你确定要关闭窗
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _ Handles Me.Load, Me.For
我是一名优秀的程序员,十分优秀!