对于我来说,很明显,如果我有一个触发事件的按钮,但是在以下情况下,我想弹出一个对话框。下面的代码一团糟,我不知道该怎么做。我认为异步/等待是其中的一部分,但在这种情况下我不清楚。
class TaskObject : Form
{
public void MyFunc()
{
MyDialog d = new MyDialog(this);
d.ShowDialog(); // I don't want any other interaction except this dialog's controls
}
internal async Task<bool> LongFunction()
{
// ...
return true;
}
}
class MyDialog : Form
{
Task<bool> task;
public async MyDialog(TaskObject o)
{
task = new Task<bool>(o.LongFunction);
await task;
}
void when_LongFunction_does_something_interesting()
{
this.MyTextBox.Text = "Something interesting";
}
void when_task_completes()
{
this.CancelButton.Visible = false;
this.CloseButton.Visible = true;
}
}
答案 0 :(得分:1)
这里有两点:
表单的构造函数不能具有async
修饰符。另外,您也可以使用Load
event。
(可选),您无需将“父”表单的实例传递给构造函数,如果改为使用Owner
,则可以直接从ShowDialog(this)
属性获取它的ShowDialog()
。
此外,完成处理后,请记住要丢弃任何对话框形式。最好将其用法包装在using
block中。
这就是我要怎么做;以TaskObject
格式:
internal async Task<bool> LongFunction()
{
// Do some magic.
// await ...
return true;
}
public void MyFunc()
{
using (MyDialog d = new MyDialog())
{
d.ShowDialog(this);
}
}
以MyDialog
格式:
private async void MyDialog_Load(object sender, EventArgs e)
{
TaskObject owner = this.Owner as TaskObject;
await owner.LongFunction();
when_task_completes();
}
如果您还想跟踪LongFunction
的进度,可以向其中添加一个Progress<T>
参数,如下所示使用它:
internal async Task<bool> LongFunction(IProgress<string> progress)
{
// Do some magic.
progress.Report("Something interesting");
// await ...
// More magic.
return true;
}
然后您可以执行以下操作:
private async void MyDialog_Load(object sender, EventArgs e)
{
TaskObject owner = this.Owner as TaskObject;
var progress = new Progress<string>(s => when_LongFunction_does_something_interesting(s));
await owner.LongFunction(progress);
when_task_completes();
}
void when_LongFunction_does_something_interesting(string message)
{
this.MyTextBox.Text = message;
}
请注意,我以Progress<string>
为例。您可以使用最适合您情况的任何类型来代替string
。