Esto es probable TL; DR para muchos, pero creo que comparar await con BackgroundWorkeres como comparar manzanas y naranjas y mis pensamientos sobre esto son los siguientes:
BackgroundWorkerestá destinado a modelar una única tarea que desea realizar en segundo plano, en un subproceso de grupo de subprocesos. async/ awaites una sintaxis para esperar asincrónicamente operaciones asincrónicas. Esas operaciones pueden o no usar un subproceso de grupo de subprocesos o incluso usar cualquier otro subproceso . Entonces, son manzanas y naranjas.
Por ejemplo, puede hacer algo como lo siguiente con await:
using (WebResponse response = await webReq.GetResponseAsync())
{
using (Stream responseStream = response.GetResponseStream())
{
int bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length);
}
}
Pero, probablemente nunca modelarías eso en un trabajador en segundo plano, probablemente harías algo como esto en .NET 4.0 (antes await):
webReq.BeginGetResponse(ar =>
{
WebResponse response = webReq.EndGetResponse(ar);
Stream responseStream = response.GetResponseStream();
responseStream.BeginRead(buffer, 0, buffer.Length, ar2 =>
{
int bytesRead = responseStream.EndRead(ar2);
responseStream.Dispose();
((IDisposable) response).Dispose();
}, null);
}, null);
Observe la desunión de la eliminación en comparación entre las dos sintaxis y cómo no puede usar usingsinasync / await.
Pero, no harías algo así con eso BackgroundWorker. BackgroundWorkerPor lo general, es para modelar una sola operación de larga duración que no desea afectar la capacidad de respuesta de la interfaz de usuario. Por ejemplo:
worker.DoWork += (sender, e) =>
{
int i = 0;
// simulate lengthy operation
Stopwatch sw = Stopwatch.StartNew();
while (sw.Elapsed.TotalSeconds < 1)
++i;
};
worker.RunWorkerCompleted += (sender, eventArgs) =>
{
// TODO: do something on the UI thread, like
// update status or display "result"
};
worker.RunWorkerAsync();
Realmente no hay nada allí con lo que pueda usar async / wait, BackgroundWorkerestá creando el hilo para usted.
Ahora, podría usar TPL en su lugar:
var synchronizationContext = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
int i = 0;
// simulate lengthy operation
Stopwatch sw = Stopwatch.StartNew();
while (sw.Elapsed.TotalSeconds < 1)
++i;
}).ContinueWith(t=>
{
// TODO: do something on the UI thread, like
// update status or display "result"
}, synchronizationContext);
En cuyo caso, TaskSchedulerestá creando el hilo para usted (asumiendo el valor predeterminado TaskScheduler), y podría usar awaitlo siguiente:
await Task.Factory.StartNew(() =>
{
int i = 0;
// simulate lengthy operation
Stopwatch sw = Stopwatch.StartNew();
while (sw.Elapsed.TotalSeconds < 1)
++i;
});
// TODO: do something on the UI thread, like
// update status or display "result"
En mi opinión, una comparación importante es si estás informando progreso o no. Por ejemplo, puede tener BackgroundWorker likeesto:
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.ProgressChanged += (sender, eventArgs) =>
{
// TODO: something with progress, like update progress bar
};
worker.DoWork += (sender, e) =>
{
int i = 0;
// simulate lengthy operation
Stopwatch sw = Stopwatch.StartNew();
while (sw.Elapsed.TotalSeconds < 1)
{
if ((sw.Elapsed.TotalMilliseconds%100) == 0)
((BackgroundWorker)sender).ReportProgress((int) (1000 / sw.ElapsedMilliseconds));
++i;
}
};
worker.RunWorkerCompleted += (sender, eventArgs) =>
{
// do something on the UI thread, like
// update status or display "result"
};
worker.RunWorkerAsync();
Pero no se ocuparía de algo de esto porque arrastraría y soltaría el componente de trabajador de fondo en la superficie de diseño de un formulario, algo que no puede hacer con async/ awaity Task... es decir, ganó ' t cree manualmente el objeto, establezca las propiedades y configure los controladores de eventos. solo llenarías el cuerpo de la DoWork,RunWorkerCompleted y ProgressChangedlos controladores de eventos.
Si "convertiste" eso en asíncrono / espera, harías algo como:
IProgress<int> progress = new Progress<int>();
progress.ProgressChanged += ( s, e ) =>
{
// TODO: do something with e.ProgressPercentage
// like update progress bar
};
await Task.Factory.StartNew(() =>
{
int i = 0;
// simulate lengthy operation
Stopwatch sw = Stopwatch.StartNew();
while (sw.Elapsed.TotalSeconds < 1)
{
if ((sw.Elapsed.TotalMilliseconds%100) == 0)
{
progress.Report((int) (1000 / sw.ElapsedMilliseconds))
}
++i;
}
});
// TODO: do something on the UI thread, like
// update status or display "result"
Sin la capacidad de arrastrar un componente a una superficie de diseñador, realmente depende del lector decidir cuál es "mejor". Pero, para mí, esa es la comparación entre awaity BackgroundWorkerno si puedes esperar métodos incorporados como Stream.ReadAsync. por ejemplo, si estaba usando BackgroundWorkersegún lo previsto, podría ser difícil de convertir para usar await.
Otros pensamientos: http://jeremybytes.blogspot.ca/2012/05/backgroundworker-component-im-not-dead.html