Async-await предназначен для того, чтобы ваша программа не ожидала, пока другой процесс завершит свою работу в течение относительно короткого времени.Подумайте об ожидании результатов запроса к базе данных, чтении файла, получении данных из базы данных и т. Д.
Если вы используете async-await, ваш поток не будет бездействовать, пока другая обработка выполняет запрос.Вместо этого if может оглянуться и посмотреть, есть ли другие дела.
Конечно, вы можете добиться того же эффекта, создав отдельный поток для ожидания.Кроме того, это сделает ваш код более сложным, создание отдельного потока отнимает много времени.
Если вы хотите запустить длительный процесс, подумайте о секундах, может быть, минуты или даже больше, необходимого временизапуск этого отдельного потока больше не важен.
Так что в вашем случае я бы посоветовал использовать BackgroundWorker
Если вашему фоновому работнику нужно много процедурчтобы выполнить свою работу, рассмотрите возможность получения из BackgroundWorker и начните работать с переопределением BackgroundWorker.OnDoWork
.
. В вашем случае фоновому работнику нужна только небольшая функция, поэтому для подписки на событие DoWork
будет достаточно.
Используйте набор инструментов Visual Studio для добавления фонового редактора или добавьте его вручную в конструкторе:
// Constructor:
public Form1()
{
InitializeComponent();
// Create a backgroundworker
this.backgroundWorker = new BackgroundWorker
{
// only if you want to display something during processing:
WorkerReportsProgress = true,
WorkerSupportsCancellation = true; // to neatly close your form
};
this.backgroundWorker.DoWork += this.BackgroundProcedure;
this.backgroundWorker.ProgressChanged += this.BackgroundProcessReport;
this.backgroundWorker.RunworkerCompleted += this.BackgroundWorkerFinished;
}
Запуск и остановка просты:
bool IsBackGroundWorkerBusy => this.backgroundWorker.IsBusy;
void StartBackgroundWork()
{
if (this.IsBackGroundWorkerbusy) return; // already started;
this.DisplayBackgroundWorkerActive(); // for example, show an ajax loader
this.backgroundWorker.RunworkerAsync();
// or if you want to start with parameters:
MyParameters backgroundWorkerParameters = new MyParameters(...);
this.backgroundWorker.RunworkerAsync(backgroundWorkerParameters);
}
void RequestCancelBackgroundWork()
{
this.DisplayBackgroundWorkerStopping();
this.backgroundWorker.CancelAsync();
}
Фоновая процедура .Это выполняется фоновым потоком.Вы не можете вызвать любую функцию, связанную с пользовательским интерфейсом в этой процедуре.Если вы хотите обновить что-либо в пользовательском интерфейсе, используйте ReportProgress.
void BackGroundProcedure(object sender, DoworkEventArgs e)
{
// if you know that the backgroundworker is started with parameters:
MyParameters parameters = (MyParameters)e.Argument;
// do you work, regularly check if cancellation is requested:
while (!e.Cancel)
{
...
// only if progress reports are needed: report some progress, not too often!
MyProgressParams progressParams = new MyProgressParams(...);
this.ReportProgress(..., progressParams);
}
// if here, the thread is requested to cancel
// if needed report some result:
e.Result = ...;
}
Progress Report .Он выполняется вашим потоком пользовательского интерфейса, поэтому при желании вы можете обновить элементы пользовательского интерфейса.Это основная функциональность этого метода.
Первым параметром в ходе выполнения отчета является число, обычно от 0..100, которое используется получателями события прогресса для обновления некоторого визуального отображения прогресса.Если у вас нет каких-либо указаний на то, как долго требуется прогресс, не используйте это значение.ProgressParams может быть любым объектом.
void BackgroundProcessReport(object sender, ProgressChangedEventArgs e)
{
// the background worker reported some progress.
... // update UI
}
Runworker Completed вызывается после завершения потока.Содержит данные, присвоенные e.Result.Он выполняется потоком пользовательского интерфейса, поэтому вы можете делать любые связанные с пользовательским интерфейсом вещи, которые вам нужны:
void BackgroundWorkerFinished(object sender, RunWorkerCompletedEventArgs e)
{
this.DisplayBackgroundWorkerFinished(); // for example: hide ajax loader
... // use e to process result
}
Аккуратное закрытие вашей формы
Если ваша форма закрывается, фоновый работник должензакончить до того, как окно можно будет утилизировать.Правильный метод использует событие OnClosing:
bool closeFormRequested = false;
void OnFormClosing(object sender, CancelEventArgs e)
{
// if background worker busy: request cancellation; can't close the form right now
if (this.IsBackgroundworkerBusy)
{
this.closeFormRequested = true;
e.Cancel = true;
this.RequestCancelBackgroundWork();
}
else
{ // background worker not busy, OK to close
e.Cancel = false;
}
}
Через некоторое время фоновый работник сообщает, что оно завершено:
void BackgroundWorkerFinished(object sender, RunWorkerCompletedEventArgs e)
{
this.DisplayBackgroundWorkerFinished();
... // process result
// if requested: close the form:
if (this.closeFormRequested)
this.Close();
}
this.Close()
приведет к OnFormClosing
, но этоесли фоновый работник не будет занят, и закрытие будет продолжено
Наконец: фоновый работник реализует IDisposable, не забудьте удалить его, когда ваша форма будет удалена.