异步ShowDialog
我正在使用async / await从数据库异步加载我的数据,在加载过程中,我想弹出一个加载表单,它只是一个带有运行进度条的简单表单,表示有一个正在运行的进程。 加载数据后,对话框将自动关闭。 我怎样才能做到这一点? 以下是我目前的代码:
protected async void LoadData() { ProgressForm _progress = new ProgressForm(); _progress.ShowDialog() // not working var data = await GetData(); _progress.Close(); }
更新:
我设法通过更改代码来使其工作:
protected async void LoadData() { ProgressForm _progress = new ProgressForm(); _progress.BeginInvoke(new System.Action(()=>_progress.ShowDialog())); var data = await GetData(); _progress.Close(); }
这是正确的方式还是有更好的方法?
谢谢你的帮助。
使用Task.Yield
很容易实现,就像这样(WinForms,为简单起见,没有exception处理):
namespace WinFormsApp { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } async Task LoadDataAsync() { await Task.Delay(2000); return 42; } private async void button1_Click(object sender, EventArgs e) { var progressForm = new Form() { Width = 300, Height = 100, Text = "Please wait... " }; var progressFormTask = progressForm.ShowDialogAsync(); var data = await LoadDataAsync(); progressForm.Close(); await progressFormTask; MessageBox.Show(data.ToString()); } } internal static class DialogExt { public static async Task ShowDialogAsync(this Form @this) { await Task.Yield(); if (@this.IsDisposed) return DialogResult.OK; return @this.ShowDialog(); } } }
重要的是要理解执行流如何跳转到新的嵌套消息循环(模式对话框的循环),然后返回到原始消息循环(这就是await progressFormTask
的用途)。
这是一个使用Task.ContinueWith的表单,应该避免使用模态ProgressForm的任何竞争条件:
protected async void LoadDataAsync() { ProgressForm _progress = new ProgressForm(); // 'await' long-running method by wrapping inside Task.Run await Task.Run(new Action(() => { // Display dialog modally // - Use BeginInvoke here to avoid blocking // and illegal cross threading exception this.BeginInvoke(new Action(() => { _progress.ShowDialog(); })); // Begin long-running method here LoadData(); })).ContinueWith(new Action(task => { // Close modal dialog // - No need to use BeginInvoke here // because ContinueWith was called with TaskScheduler.FromCurrentSynchronizationContext() _progress.Close(); }), TaskScheduler.FromCurrentSynchronizationContext()); }
ShowDialog()
是一个阻塞调用; 在用户关闭对话框之前,执行不会进入await
语句。 请改用Show()
。 不幸的是,您的对话框不是模态的,但它将正确跟踪异步操作的进度。
您可以尝试以下方法:
上述就是C#学习教程:异步ShowDialog分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
protected async void LoadData() { ProgressForm _progress = new ProgressForm(); var loadDataTask = GetData(); loadDataTask.ContinueWith(a => this.Invoke((MethodInvoker)delegate { _progress.Close(); })); _progress.ShowDialog(); }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1011864.html