c# - C# 考试 70-483 参考书示例错了吗?(父/子线程)
问题描述
在C# 70-483 Exam Ref的第一版中,示例 1-12 给出了将子任务附加到父任务的示例。我认为这是错误的,并希望有人在继续此假设之前检查我的理解。示例中的代码如下:
using System;
using System.Threading.Tasks;
namespace Chapter1
{
public static class Program
{
public static void Main()
{
Task<Int32[]> parent = Task.Run(() =>
{
var results = new Int32[3];
new Task(() => results[0] = 0, TaskCreationOptions.AttachedToParent).Start();
new Task(() => results[1] = 1, TaskCreationOptions.AttachedToParent).Start();
new Task(() => results[2] = 2, TaskCreationOptions.AttachedToParent).Start();
return results;
});
var finalTask = parent.ContinueWith(parentTask =>
{
foreach (var i in parentTask.Result)
{
Console.WriteLine(i);
}
});
finalTask.Wait();
}
}
}
问题在于Task.Run
. MSDN 解释说这不允许附加子任务。我认为这可能是 .NET 版本在出版时(2013 年)的问题,但 MSDN 文章是在本书出版前两年发表的。
这特别棘手,因为如果执行上面的代码,results
数组确实会将其值设置为 0、1 和 2。但是,如果 lambda 执行的操作比这更耗时,则不会在该索引处设置任何值数组。
例如,下面的代码results
分别将“一”和“二”分配给元素 1 和 2,但元素 0 为空。
using System;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Chapter1
{
public static class Program
{
public static void Main()
{
Task<String[]> parent = Task.Run(() =>
{
var results = new String[3];
new Task(() => {
SHA256 mySHA256 = SHA256.Create();
byte[] messageBytes = Encoding.ASCII.GetBytes("asdf");
byte[] hashBytes = mySHA256.ComputeHash(messageBytes);
results[0] = BitConverter.ToString(hashBytes).Replace("-", "");
}, TaskCreationOptions.AttachedToParent).Start();
new Task(() => results[1] = "one", TaskCreationOptions.AttachedToParent).Start();
new Task(() => results[2] = "two", TaskCreationOptions.AttachedToParent).Start();
return results;
});
var finalTask = parent.ContinueWith(parentTask =>
{
foreach (var i in parentTask.Result)
{
Console.WriteLine(i);
}
});
finalTask.Wait();
}
}
}
当我使用任务工厂(示例中未显示)启动父任务时,一切都按预期工作并TaskCreationOptions
影响子线程的同步。
所以我的问题是:
- 我的理解是否正确,传递
TaskCreationOptions.AttachedToParent
到下创建的子任务是没有意义的Thread.Run
? - 我的假设是否正确,即本书的示例仅有效,因为子任务 lambda 只是执行在父线程终止之前恰好完成的分配?
解决方案
我相信您的两个问题(断言)都是正确的。这篇 MSDN文章似乎很好地涵盖了它。
Re 2,正如文章所说,传递AttachedToParent
给一个任务开始时Task.Run()
会产生“不可预测的”结果,其中一个就是你观察到的结果。
我应该添加一个细微差别,即“子”任务将在ContinueWith()
开始后继续运行,因此它们在相应的Console.WriteLine()
.
推荐阅读
- python - 如何直接在文件中添加输出数据
- javascript - 有人可以解释这个 Javascript 选项卡代码吗
- gem5 - Root-NFS:没有可用的 NFS 服务器,放弃。VFS: 无法通过 NFS 挂载 root fs,尝试使用软盘。完整系统模式下的 Gem5 X86 错误
- php - 使用简单的 HTML Dom 从 HTML 页面中抓取数据
- node.js - Nodejs AWS S3 deleteObject() 如果输入缺少的键,你会发现它 DeleteMarker true
- python - 使用 CDK 创建 AWS RDS Postgres 并定义安全组
- haskell - 递归函数中的Haskell多态推断/使用输入类型签名?
- python - 写爬虫的时候为什么用xpath不能得到结果?
- c - 对文件使用 getc
- python - 如何使用循环将火花数据帧转换为 python 数据帧