使用语句中的异步方法
注意:我在Unity中使用C#,这意味着.NET 3.5版本,所以我不能使用await
或async
关键字..
当我在其中放入一个异步工作的方法时, 使用语句会发生什么?
using (WebClient wc = new WebClient()) { wc.DownloadFileAsync(urlUri, outputFile); } SomeMethod1(); SomeMethod2();
如您所知,在调用DownloadFileAsync()
方法之后,将调用SomeMethod1()
,它不在using
块中,而DownloadFileAsync()
仍然有效 。 所以现在我真的很困惑在这种情况下使用语句和异步方法会发生什么。
是否会在正确的时间调用wc
Dispose()
而没有任何问题?
如果没有,我该如何更正此示例?
来自评论:
那怎么办呢? 只需添加await关键字?
不,你不能这样做。 (这就是为什么之前提出的重复问题实际上并不重复……你的情况略有不同。)你需要延迟处理直到下载完成,但是由于你需要再执行两个程序语句,这很复杂(至少……如果没有一个好的, 最小的 , 完整的代码示例,就不可能确定。
我认为你应该切换到等待的WebClient.DownloadFileTaskAsync()
方法,因为这至少会简化实现,使得保留using
语句变得简单。
您可以通过捕获返回的Task
对象来解决问题的其他部分,直到执行其他程序语句之后才等待它:
using (WebClient wc = new WebClient()) { Task task = wc.DownloadFileTaskAsync(urlUri, outputFile); SomeMethod1(); SomeMethod2(); await task; }
通过这种方式,可以启动下载,调用其他两个方法, 然后代码将等待下载完成。 只有在它完成后才会退出using
块,允许处理WebClient
对象。
当然,在您当前的实现中,您无疑正在处理适当的DownloadXXXCompleted
事件。 如果需要,可以继续使用该方式。 但恕我直言,一旦你切换到使用await
,只需在await
完成操作后需要执行的代码之后再放。 这使得所有代码都与操作保持在一个位置并简化了实现。
如果由于某种原因你不能使用await
,那么你将不得不使用一些替代机制来延迟WebClient
的处理。 某些方法将允许您继续using
,其他方法将要求您在DownloadXXXCompleted
事件处理程序中调用Dispose()
。 如果没有更完整的代码示例,并且明确解释为什么await
不合适,那么就不可能确定最佳替代方案是什么。
编辑:
由于您已确认在当前代码中无法访问await
,因此以下是与旧代码兼容的其他两个选项…
一种可能性是在开始操作后在同一个线程中等待:
using (WebClient wc = new WebClient()) { object waitObject = new object(); lock (waitObject) { wc.DownloadFileCompleted += (sender, e) => { lock (waitObject) Monitor.Pulse(waitObject); }; wc.DownloadFileAsync(urlUri, outputFile); SomeMethod1(); SomeMethod2(); Monitor.Wait(waitObject); } }
(注意:可以使用上面任何合适的同步,例如ManualResetEvent
, CountdownEvent
,甚至Semaphore
和/或“slim”等效。我使用Monitor
只是因为它的简单性和效率,并且考虑到读者可以调整以适应他们的首选一种显而易见的原因是人们可能更喜欢Monitor
以外的其他东西,其他类型的同步技术不会冒着让DownloadFileCompleted
事件处理程序本身阻塞等待SomeMethod1()
和SomeMethod2()
方法完成的SomeMethod2()
。这是否重要当然取决于与文件下载相比这些方法调用需要多长时间。)
但是,上面将阻止当前线程。 在某些情况下,这可能没问题,但大多数情况下,操作是在UI线程中启动的,并且在操作期间不应该阻止该线程。 在这种情况下,您将完全放弃using
,只需从完成事件处理程序中调用Dispose()
:
WebClient wc = new WebClient(); wc.DownloadFileCompleted += (sender, e) => { wc.Dispose(); }; wc.DownloadFileAsync(urlUri, outputFile); SomeMethod1(); SomeMethod2();
System.Net.WebClient
提供事件DownloadFileCompleted
。 您可以为该事件添加处理程序并在此时处置客户端。
- .NET 3.5的哪些function可以在.NET 2.0应用程序中使用?
- C#Project Global AssemblyInfo
- 在C#/ .NET3.5中构建动态SQL查询的最佳方法?
- 有没有办法做到这一点,在List .ForEach()语句中分配一个值?
- 调用INotifyPropertyChanged的PropertyChanged事件的最佳方法是什么?
- WebService添加布尔参数时消耗的WCF?
- 如果设置了PipeSecurity,则在创建第二个实例时,命名管道服务器会抛出UnauthorizedAccessException
- .NET 3.5 | 绑定到视图模型属性时,WPF Textbox拒绝更新自身
- 通过reflection创建委托