我使用异步/等待从数据库异步加载数据,在加载过程中,我想弹出一个加载表单,它只是一个简单的表单,带有正在运行的进度条,以指示存在一个正在运行的进程。加载数据后,对话框将自动关闭。我怎样才能做到这一点?下面是我的当前代码:
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();
}这是正确的方式还是有更好的方法?
谢谢你的帮助。
发布于 2015-10-29 09:58:33
使用Task.Yield很容易实现,如下所示(WinForms,为简单起见没有异常处理)。了解执行流在这里如何跳到新的嵌套消息循环(模态对话框的消息循环),然后返回到原始消息循环(这就是await progressFormTask的作用)是很重要的:
namespace WinFormsApp
{
internal static class DialogExt
{
public static async Task<DialogResult> ShowDialogAsync(this Form @this)
{
await Task.Yield();
if (@this.IsDisposed)
return DialogResult.Cancel;
return @this.ShowDialog();
}
}
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
async Task<int> 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... " };
object data;
var progressFormTask = progressForm.ShowDialogAsync();
try
{
data = await LoadDataAsync();
}
finally
{
progressForm.Close();
await progressFormTask;
}
// we got the data and the progress dialog is closed here
MessageBox.Show(data.ToString());
}
}
}发布于 2017-04-14 22:36:01
下面是一种使用Task.ContinueWith的模式,在使用模态ProgressForm时应该避免任何争用条件:
protected async void LoadDataAsync()
{
var progressForm = 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(() =>
{
progressForm.ShowDialog();
}));
// Begin long-running method here
LoadData();
})).ContinueWith(new Action<Task>(task =>
{
// Close modal dialog
// No need to use BeginInvoke here
// because ContinueWith was called with TaskScheduler.FromCurrentSynchronizationContext()
progressForm.Close();
}), TaskScheduler.FromCurrentSynchronizationContext());
}发布于 2015-10-29 06:03:48
ShowDialog()是一个阻塞调用;在用户关闭对话框之前,执行不会提前到await语句。使用Show()代替。不幸的是,您的对话框将不是模态,但它将正确跟踪异步操作的进度。
https://stackoverflow.com/questions/33406939
复制相似问题