#c# #winforms #async-await
#c# #winforms #асинхронное ожидание
Вопрос:
Мне понятно, если у меня есть кнопка, которая запускает событие, но в приведенном ниже случае я хочу открыть диалоговое окно. Приведенный ниже код представляет собой беспорядок, я не знаю, как это сделать правильно. Я думаю, что async / await является частью этого, но я не совсем понимаю этот случай.
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;
}
}
Комментарии:
1. Оно вызывается
ShowDialog()
, а неShowModal()
.2. Что? Мой вопрос на 100% отличается, Ахмед. Речь идет о том, как заставить диалог работать параллельно с запущенной задачей.
3. «Это о том, как заставить диалог работать параллельно с запущенной задачей». Где выполняется эта задача? В «родительской» форме?
4. Видишь конструктор? Это создание задачи и ее выполнение. Но этот код не компилируется. Я хочу, чтобы диалоговое окно запускалось во время выполнения фоновой задачи, а затем задача вызывала диалоговое окно для выполнения каких-либо действий.
5. Предполагая, что
TaskObject
является производным отForm
иLongFunction
является общедоступным / внутренним методом вo
экземпляре этой формы, вы можете просто сделать этот метод асинхронным, а затем вызвать его (иawait
это) в модальной форме. форма. Вы пробовали это? Пожалуйста, включитеLongFunction
метод в свой вопрос (или, по крайней мере, подпись этого метода).
Ответ №1:
Здесь есть два момента:
-
Конструктор вашей формы не может иметь
async
модификатор. В качестве альтернативы вы можете использовать вместо этогоLoad
событие. -
(Необязательно) Вам не нужно передавать экземпляр «родительской» формы конструктору, вы можете получить его непосредственно из
Owner
свойства, если используетеShowDialog(this)
вместоShowDialog()
.
Кроме того, не забудьте удалить любую диалоговую форму после того, как вы закончите с ней. Желательно, чтобы его использование было заключено в using
блок.
Вот как я бы это сделал; В 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
вы можете использовать любой тип, который лучше всего подходит для вашей ситуации.
Комментарии:
1. Большое вам спасибо за усилия, которые вы приложили, чтобы помочь мне. Я сейчас пробую это, и если это сработает, поставлю галочку.
2. Обновление: в итоге я отказался от стиля async / await. Вместо этого диалоговое окно запускает код в отдельно управляемом потоке (поэтому функция диалога может просто вернуться), и этот код вызовет диалоговое окно для выполнения обновлений. Итак, к сожалению, полный тест невозможен, но, по крайней мере, часть о событии загрузки все еще полезна для меня. Еще раз спасибо!