繁体   English   中英

使用语句中的异步方法

[英]Asynchronous methods in using statement

注意:我在Unity中使用C#,这意味着.NET 3.5版本,所以我不能使用awaitasync关键字..

当我在其中放入异步工作的方法时, 使用语句会发生什么?

using (WebClient wc = new WebClient()) {
    wc.DownloadFileAsync(urlUri, outputFile);
}
SomeMethod1();
SomeMethod2();

如您所知,在调用DownloadFileAsync()方法之后,将调用SomeMethod1() ,它不在using块中,而DownloadFileAsync()仍然有效 所以现在我真的很困惑在这种情况下using语句和异步方法会发生什么。

是否会在正确的时间调用wc Dispose()而没有任何问题?

如果没有,我该如何更正此示例?

来自评论:

那我怎么避免这个呢? 只需添加await关键字?

不,你不能做到这一点。 (这就是为什么之前提出的重复问题实际上并不重复......你的情况略有不同。)你需要延迟处理,直到下载完成,但是由于你需要再执行两个程序语句,这很复杂(至少......如果没有一个好的, 最小的完整的代码示例,就不可能确定。

认为你应该切换到awaitable 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);
    }
}

但是,上面将阻止当前线程。 在某些情况下,这可能没问题,但大多数情况下,操作是在UI线程中启动的,并且在操作期间不应阻止该线程。 在这种情况下,您将完全放弃using ,只需从完成事件处理程序中调用Dispose()

WebClient wc = new WebClient();
wc.DownloadFileCompleted += (sender, e) =>
{
    wc.Dispose();
};
wc.DownloadFileAsync(urlUri, outputFile);
SomeMethod1();
SomeMethod2();

System.Net.WebClient提供事件DownloadFileCompleted 您可以为该事件添加处理程序并在那时处置客户端。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM