我试图理解究竟是什么,在C#中,使用async await
的方法正在做什么。
考虑以下两个例子:
static async Task<byte[]> MyReadAsync1(Stream source)
{
var result = new byte[1024];
int readBytes = 0;
while (readBytes != result.Length)
{
int singleRead = await source.ReadAsync(result, readBytes, result.Length - readBytes);
if (singleRead == 0)
break;
readBytes += singleRead;
}
if (readBytes == result.Length)
return result;
return result.Take(readBytes).ToArray();
}
static Task<byte[]> MyReadAsync2(Stream source)
{
return Task.Run(() =>
{
var result = new byte[1024];
int readBytes = 0;
while (readBytes != result.Length)
{
int singleRead;
try
{
singleRead = source.ReadAsync(result, readBytes, result.Length - readBytes).Result;
}
catch (AggregateException e)
{
ExceptionDispatchInfo.Capture(e.InnerException).Throw();
}
if (singleRead == 0)
break;
readBytes += singleRead;
}
if (readBytes == result.Length)
return result;
return result.Take(readBytes).ToArray();
});
}
我的问题是:这两种方法是否相同?
如果我执行它们,它看起来就像是。它们都没有阻塞调用线程。就我所知,他们正在做同样的事情,即使在抛出任何异常的情况下也是如此。
如果它们真的相同,编译器是否会产生相同的代码?这是否意味着async await
除了保存我输入一些样板代码,启动一个任务并解开AggregateExceptions之外什么也不做呢?
如果存在差异,究竟是什么,如果没有async await
,是否可以实现完全相同的行为?
注意:我已经看到问题What is the purpose of “return await” in C#?,我理解那里给出的答案。但这只涉及一个单一的返回声明的情况,而我的问题意味着更一般。
我没有质疑async await
的目的,我只是想详细了解它。
更新
possible duplicate没有回答我的问题。该问题仅涵盖一行代码,比较.Result
和await
。在我的问题中,我有很多额外的代码,这些代码是&#34;混合&#34;使用异步代码并在MyReadAsync2
方法中将整个执行包装在Task.Run
中。我无法看到另一个问题是如何解决这些额外问题的。
答案 0 :(得分:1)
粗略地说,如果你想写一个&#34; await
免费&#34;代码的版本,您在与Result
大致相同的位置使用ContinueWith
,而不是使用await
(如上所述,将阻止 a < / em> thread并可能导致死锁。)
当然,这忽略了同步上下文机制,例如,如果这是调用原始方法的上下文,则可以使您的代码在UI线程上运行。您还会发现(如果您有多个await
)您的嵌套级别发疯并且您无法轻松使用某些构造(例如,尝试在ContinueWith
内部执行async
一个循环,然后尝试使用await
1,2 )编写等效项。
有async
/ async
给你的很多机器,你不必经常偷看幕后。但是,如果您愿意,您可以尝试编译一些基于async
的代码,然后通过一个不支持await
的反编译器运行它,或者可以选择不尝试反向工程async
方法。
1 在大多数情况下,并非简单的循环只是调用ContinueWith
是.data\maven\configjar\configjar.log
代码的典型示例。
2 请注意,在此示例中,循环的每次迭代仅在前一个等待完成时开始 - 因此您必须将循环上下文传递给您的任何方法#39;重新转到The system cannot find the path specified.
来电。