Async / await vs BackgroundWorker

在过去的几天里,我测试了.net 4.5和c#5的新功能。

我喜欢它的新async / await功能。之前我曾使用BackgroundWorker通过响应式UI在后台处理更长的进程。

我的问题是:在拥有这些不错的新功能之后,我何时应该使用async / await和什么时候使用BackgroundWorker?两者的常见情况是什么?


哆啦的时光机
浏览 760回答 3
3回答

猛跑小猪

async / await旨在替换诸如BackgroundWorker。之类的结构。如果你愿意,你当然可以使用它,你应该能够使用async / await和其他一些TPL工具来处理那里的所有内容。由于两者都起作用,因此归结为个人偏好,以及您何时使用。什么对你更快?什么是更容易为你理解吗?

吃鸡游戏

这可能是TL; DR为多,但是,我认为比较await有BackgroundWorker就是喜欢上了这后续比较苹果和桔子和我的想法:BackgroundWorker用于在线程池线程上为您要在后台执行的单个任务建模。&nbsp; async/ await是异步等待异步操作的语法。这些操作可能会也可能不会使用线程池线程甚至使用任何其他线程。所以,他们是苹果和橘子。例如,您可以执行以下操作await:using (WebResponse response = await webReq.GetResponseAsync()){&nbsp; &nbsp; using (Stream responseStream = response.GetResponseStream())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; int bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length);&nbsp; &nbsp; }}但是,您可能永远不会在后台工作程序中对此进行建模,您可能会在.NET 4.0(之前await)中执行类似的操作:webReq.BeginGetResponse(ar =>{&nbsp; &nbsp; WebResponse response = webReq.EndGetResponse(ar);&nbsp; &nbsp; Stream responseStream = response.GetResponseStream();&nbsp; &nbsp; responseStream.BeginRead(buffer, 0, buffer.Length, ar2 =>&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; int bytesRead = responseStream.EndRead(ar2);&nbsp; &nbsp; &nbsp; &nbsp; responseStream.Dispose();&nbsp; &nbsp; &nbsp; &nbsp; ((IDisposable) response).Dispose();&nbsp; &nbsp; }, null);}, null);请注意比较了两种语法,以及如何你不能使用的处置不相交using无async/ await。但是,你不会做那样的事情BackgroundWorker。&nbsp; BackgroundWorker通常用于建模您不希望影响UI响应的单个长时间运行操作。例如:worker.DoWork += (sender, e) =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int i = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // simulate lengthy operation&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Stopwatch sw = Stopwatch.StartNew();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (sw.Elapsed.TotalSeconds < 1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };worker.RunWorkerCompleted += (sender, eventArgs) =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // TODO: do something on the UI thread, like&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // update status or display "result"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };worker.RunWorkerAsync();你真的没有什么可以使用async / await,BackgroundWorker为你创建线程。现在,您可以使用TPL代替:var synchronizationContext = TaskScheduler.FromCurrentSynchronizationContext();Task.Factory.StartNew(() =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int i = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // simulate lengthy operation&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Stopwatch sw = Stopwatch.StartNew();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (sw.Elapsed.TotalSeconds < 1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }).ContinueWith(t=>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // TODO: do something on the UI thread, like&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // update status or display "result"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, synchronizationContext);在这种情况下,TaskScheduler为您创建线程(假设默认值TaskScheduler),并可以使用await如下:await Task.Factory.StartNew(() =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int i = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // simulate lengthy operation&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Stopwatch sw = Stopwatch.StartNew();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (sw.Elapsed.TotalSeconds < 1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });// TODO: do something on the UI thread, like// update status or display "result"在我看来,一个重要的比较是你是否报告进展。例如,你可能有BackgroundWorker like这个:BackgroundWorker worker = new BackgroundWorker();worker.WorkerReportsProgress = true;worker.ProgressChanged += (sender, eventArgs) =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // TODO: something with progress, like update progress bar&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };worker.DoWork += (sender, e) =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int i = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // simulate lengthy operation&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Stopwatch sw = Stopwatch.StartNew();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (sw.Elapsed.TotalSeconds < 1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((sw.Elapsed.TotalMilliseconds%100) == 0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ((BackgroundWorker)sender).ReportProgress((int) (1000 / sw.ElapsedMilliseconds));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;};worker.RunWorkerCompleted += (sender, eventArgs) =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // do something on the UI thread, like&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // update status or display "result"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };worker.RunWorkerAsync();但是,你不会处理一些这一点,因为你会拖和拖放到窗体的设计表面的背景工作者组成部分-这是你不能做async/ await和Task...即你赢了” t手动创建对象,设置属性并设置事件处理程序。你只填写的身体DoWork,RunWorkerCompleted和ProgressChanged事件处理程序。如果您将其“转换”为异步/等待,您可以执行以下操作:&nbsp; &nbsp; &nbsp;IProgress<int> progress = new Progress<int>();&nbsp; &nbsp; &nbsp;progress.ProgressChanged += ( s, e ) =>&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// TODO: do something with e.ProgressPercentage&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// like update progress bar&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp;await Task.Factory.StartNew(() =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int i = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // simulate lengthy operation&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Stopwatch sw = Stopwatch.StartNew();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (sw.Elapsed.TotalSeconds < 1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((sw.Elapsed.TotalMilliseconds%100) == 0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; progress.Report((int) (1000 / sw.ElapsedMilliseconds))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });// TODO: do something on the UI thread, like// update status or display "result"如果没有将组件拖到Designer表面的能力,那么由读者来决定哪个“更好”。但是,对我来说,这是和之间的比较,await而BackgroundWorker不是你是否可以等待内置方法Stream.ReadAsync。例如,如果您BackgroundWorker按预期使用,可能很难转换为使用await。其他想法:http://jeremybytes.blogspot.ca/2012/05/backgroundworker-component-im-not-dead.html
打开App,查看更多内容
随时随地看视频慕课网APP