【发布时间】:2018-09-26 15:52:37
【问题描述】:
关于异步编程的 C# 文档指出:
对于受 CPU 限制的代码,您等待使用
Task.Run方法在后台线程上启动的操作。await关键字是魔法发生的地方。它将控制权交给执行await的方法的调用者,并最终允许 UI 具有响应性或服务具有弹性。当应用
await关键字时,它会暂停调用方法并将控制权交还给调用者,直到等待的任务完成。
考虑到这一点,我测试了一些 CPU 绑定代码(找到一个比特币块哈希似乎非常现代且困难),以尝试准确了解应用 async/await 时发生的情况: p>
示例
namespace AsyncronousSample
{
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
internal static class Program
{
private static async Task Main(string[] args)
{
string result = await HashAsync(Guid.NewGuid().ToByteArray(), 4);
Console.WriteLine("Calculating hash...");
Console.WriteLine(result);
Console.Read();
}
private static async Task<string> HashAsync(byte[] data, int difficulty = 1)
{
int nonce = default;
string result = default;
byte[] GetDataBytesWithNOnce()
{
return data
.Concat(BitConverter.GetBytes(nonce++))
.ToArray();
}
byte[] ComputeHash(byte[] bytes)
{
using (SHA256 sha = SHA256.Create())
{
return sha.ComputeHash(sha.ComputeHash(bytes));
}
}
string ConvertToHash(byte[] hashBytes)
{
return BitConverter
.ToString(hashBytes)
.Replace("-", string.Empty)
.ToLower();
}
return await Task.Run(() =>
{
do
{
result = ConvertToHash(ComputeHash(GetDataBytesWithNOnce()));
} while (!result.StartsWith(new string('0', difficulty)));
return result;
});
}
}
}
好的,对于那些对比特币及其工作原理感兴趣的更精明的人来说,这不是真正的比特币哈希算法,而是SHA256(SHA256(data + nonce)),所以这已经够难了举个例子。
期望与现实
我希望Calculating hash... 会立即打印到控制台,然后在最终找到哈希时打印结果。
实际上,在找到哈希之前,控制台不会打印任何内容。
问题
我的理解或代码哪里出了问题?
【问题讨论】:
-
那是因为你在打印之前
await。 -
好吧,你等着它..
-
@SLaks “应用 await 关键字时,它会暂停调用方法并将控制权交还给调用者,直到等待的任务完成。” - 在我看来,这意味着等待的方法被暂停并且 Main 方法重新获得控制权,直到等待的方法完成,最后,
Console.WriteLine(result)解决并完成? - 我知道,我可能完全不合时宜 -
它暂停调用方法(带有
async的方法)并将控制权交还给异步方法的调用者(无论调用什么方法) -
想象一下 await 将方法分成两部分,之前和之后。如果您熟悉 javascript,请想象一些始终具有 'then(...)' 延续的 ajax 查询。 await 之后的部分是这样的 'then' 延续,但按顺序编写,没有“回调地狱”。
标签: c# asynchronous async-await