- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
注意:我在 Unity 中使用 C#,这意味着版本 .NET 3.5,所以我不能使用 await
或 async
关键字。 .
当我在 using 语句 中放入一个异步 工作的方法时会发生什么?
using (WebClient wc = new WebClient()) {
wc.DownloadFileAsync(urlUri, outputFile);
}
SomeMethod1();
SomeMethod2();
如您所知,在方法 DownloadFileAsync()
被调用后, SomeMethod1()
将被调用,它在 using
block 之外而 DownloadFileAsync()
仍在工作。所以现在我真的很困惑在这种情况下 using 语句和异步方法会发生什么。
wc
的 Dispose()
会在正确的时间被调用而没有任何问题吗?
如果不是,我该如何更正这个例子?
最佳答案
来自评论:
Then how do I avoid this? Just add await keyword?
不,你不能只是那样做。 (这就是为什么之前提出的重复问题实际上不是重复的......你的场景略有不同。)你需要延迟处理直到下载完成,但由于你需要执行两个以上的程序语句(至少……如果没有 a good, minimal, complete code example 就不可能确定。
我确实认为您应该切换到可等待的WebClient.DownloadFileTaskAsync()
方法,因为这至少会简化实现,使保留 using
语句变得简单。
您可以通过捕获返回的 Task
对象并在您的其他程序语句执行之后之前等待它来解决问题的另一部分:
using (WebClient wc = new WebClient()) {
Task task = wc.DownloadFileTaskAsync(urlUri, outputFile);
SomeMethod1();
SomeMethod2();
await task;
}
这样就可以开始下载了,调用你另外两个方法,然后代码会等待下载完成。只有当它完成时才会退出 using
block ,从而允许释放 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
只是因为它的简单性和效率,并且理所当然地认为读者可以调整以适应他们喜欢的同步方式。一个明显的原因可能是人们更喜欢 other 与 Monitor
相比,其他类型的同步技术不会冒 DownloadFileCompleted
事件处理程序本身阻塞等待 SomeMethod1() 的风险
和 SomeMethod2()
方法来完成。这是否重要当然取决于与文件下载相比这些方法调用需要多长时间。)
然而,以上将阻塞当前线程。在某些情况下,这可能没问题,但大多数情况下,操作是在 UI 线程中启动的,并且在操作期间不应阻塞该线程。在这种情况下,您将希望完全放弃 using
,而只需从完成事件处理程序中调用 Dispose()
:
WebClient wc = new WebClient();
wc.DownloadFileCompleted += (sender, e) =>
{
wc.Dispose();
};
wc.DownloadFileAsync(urlUri, outputFile);
SomeMethod1();
SomeMethod2();
关于c# - using语句中的异步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33722968/
创建一个“海盗对话”,可以选择左手或右手。我希望它对“左”和“右”的不同拼写做出积极的回答(正如您将在代码中看到的那样),但是,当我为所有非“右”或“左”的输入添加最终的“else”代码时,它给了我一
With 语句 对一个对象执行一系列的语句。 With object statements End With 参数 object 必需的部分
While...Wend 语句 当指定的条件为 True 时,执行一系列的语句。 While condition  ; Version [stat
所以我正在处理的代码有一个小问题。 while True: r = input("Line: ") n = r.split() if r == " ":
我有一个对象数组: var contacts = [ { "firstName": "Akira", "lastName": "Laine", "number"
int main() { int f=fun(); ... } int fun() { return 1; return 2; } 在上面的程序中,当从main函数中调用一个
我的项目中有很多 if 语句、嵌套 if 语句和 if-else 语句,我正在考虑将它们更改为 switch 语句。其中一些将具有嵌套的 switch 语句。我知道就编译而言,switch 语句通常更
Rem 语句 包含程序中的解释性注释。 Rem comment 或 ' comment comment 参数是需要包含的注释文本。在 Rem 关键字和 comment 之间应有一个空格。
ReDim 语句 在过程级中声明动态数组变量并分配或重新分配存储空间。 ReDim [Preserve] varname(subscripts) [, varname(subscripts)]
Randomize 语句 初始化随机数生成器。 Randomize [number] number 参数可以是任何有效的数值表达式。 说明 Randomize 使用 number 参数初始
Public 语句 定义公有变量并分配存储空间。在 Class 块中定义私有变量。 Public varname[([subscripts])][, varname[([subscripts])
Sub 语句 声明 Sub 过程的名称、参数以及构成其主体的代码。 [Public [Default]| Private] Sub name [( arglist )]
Set 语句 将对象引用赋给一个variable或property,或者将对象引用与事件关联。 Set objectvar = {objectexpression | New classname
我有这个代码块,有时第一个 if 语句先运行,有时第二个 if 语句先运行。我不确定为什么会这样,因为我认为 javascript 是同步的。 for (let i = 0; i < dataObje
这是一个 javascript 代码,我想把它写成这样:如果此人回答是,则回复“那很酷”,如果此人回答否,则回复“我会让你开心”,如果此人回答的问题包含"is"或“否”,请说“仅键入”是或否,没有任何
这是我的任务,我尝试仅使用简短的 if 语句来完成此任务,我得到的唯一错误是使用“(0.5<=ratio<2 )”,除此之外,构造正确吗? Scanner scn = new Scanner(
有没有办法在 select 语句中使用 if 语句? 我不能在这个中使用 Case 语句。实际上我正在使用 iReport 并且我有一个参数。我想要做的是,如果用户没有输入某个参数,它将选择所有实例。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: If vs. Switch Speed 我将以 C++ 为例,但我要问的问题不是针对特定语言的。我的意思是一
Property Set 语句 在 Class 块中,声明名称、参数和代码,这些构成了将引用设置到对象的 Property 过程的主体。 [Public | Private] Pro
Property Let 语句 在 Class 块中,声明名称、参数和代码等,它们构成了赋值(设置)的 Property 过程的主体。 [Public | Private] Prop
我是一名优秀的程序员,十分优秀!