.NET TPL 声明问题
.NET TPL Declaration issues
我很难理解 TPL,我找不到很多关于它的清晰文章。大多数似乎使用带有 lambda 表达式的简单示例。
我有一个 C# 函数
int[] PlayGames(int[][] boardToSearch, int numGamesToPlay) {…}
我想使用 C# 中的 .NET 4.6 TPL 使其可线程化。我想一次启动最多 8 个这些功能,等到它们全部完成,捕获结果并继续。
我似乎无法获得正确的类型并且它没有按预期工作。
这是我目前得到的:
Task<int[]> PlayGames(int[][] boardToSearch, int numGamesToPlay) {…code that takes a long time…}
private int FindBestMove(int[][] boardToSearch, int numGamesToPlay)
{
…
var taskList = new List<Task>();
taskList.Add(Task.Factory.StartNew(() => { return PlayGames(boardToSearch, numGamesToPlay); }));
taskList.Add(Task.Factory.StartNew(() => { return PlayGames(boardToSearch, numGamesToPlay); }));
// Tests
Task a = taskList.First();
var a1 = a.Result; // NOT ALLOWED!? Viewable in debugger, cannot access it.
var b = Task.FromResult(a);
var b1 = b.Result; // Works but cannot access child member Result. Debugger sees it, I can’t!?
Task.WaitAll(taskList.ToArray());
…
}
这是我的问题
如何删除 lambda 表达式 () => { return PlayGames(boardToSearch, numGamesToPlay); }
?我想以某种方式使用 Func()
,但我一辈子都不知道怎么说“Task.Factory.StartNew<int[]>(Func(PlayGames(boardToSearch, numGamesToPlay)))
”。
为什么我需要使用StartNew()
?当我执行 taskList.Add(PlayGames(int[][] boardToSearch, int numGamesToPlay))
时,它会同步执行!?以这种方式将任务添加到列表的正确语法是什么?我是否需要声明我传递给 new Task(Func(PlayGames))
?
之类的某种 Func
当你在执行 Task a = taskList.First() 行后查看变量 a 时,它在调试窗格中清楚地显示了一个名为 Result 的成员。如果我扩展该结果,它包含正确的数据!但是,如果我单击向结果成员添加监视,则会出现错误!如果我这样做 a.Result,编译器会给我同样的错误!??所以调试器说它在那里,但我不能自己查看它!??我可以从对象浏览它但不能直接浏览。我附上了此屏幕截图,以便其他人可以看到。
在远离 lambda 表达式的情况下,使用 .NET 4.6 执行此操作的最简洁方法是什么。我想查看所有类型和声明。
附件是我的调试器的屏幕截图,因此您可以明白我的意思 .Result
让我们从头开始:
1] Func 它只是一个委托,它是 .net 框架库的一部分。
因此,当您传递 () => { return PlayGames(boardToSearch, numGamesToPlay); }
时,这意味着您只是创建了一个类型为 Func<int[]>
的匿名方法。如果将此 lambda 表达式分配给某个变量,则可以检查此类型。
如果你不想使用 lambda,你可以编写一个通用方法并将其放入任务中:Task.Factory.StartNew(YourMethodWhichReturnsIntArray)
.
2] 当您调用 StartNew()
方法时,它只会创建一个新的 Task
并开始执行它。而已。
taskList.Add(PlayGames(int[][] boardToSearch, int numGamesToPlay))
- 这只是将 Task
放入 taskList
。如果在您的 PlayGames
方法中此 Task
未启动,那么您需要稍后再执行此操作。同步与否- 将Task
添加到列表是同步操作,但执行仍然是异步的。任何语法都可能正确或不正确——这取决于复杂性和实现。除了 Task.Factory.StartNew()
,您还可以使用 Task.Run()
方法。它做同样的事情,但以一种更短的方式。并且在传递给 Task
.
之前没有必要声明一个 func
3] 我认为这是因为 debugger
有能力等待并行 thread/task 的结果,但 watcher
没有。这就是你得到错误的原因。
所以,我会说不要尝试为并行线程结果添加观察者(只是为了跳过可能的错误)。
4] 在远离 lambda 表达式的情况下,使用 .NET 4.6 执行此操作的最简洁方法是什么。我想查看所有类型和声明。
正如我上面所说,没有必要声明 lambda。您可以创建具有相应定义的方法。但是在这里你将参数传递给这个方法会遇到一些困难(但它们仍然可以解决)。因此,lambda - 是将函数传递给 Task
的最简单方法,因为它可以轻松地从创建这些 lambda 的范围中捕获参数。
What is the cleanest way
- 同样,这取决于。我们每个人都有自己最干净的方式来完成 运行 新任务。所以,我认为(见下文):
// your function
int[] PlayGames(int[][] boardToSearch, int numGamesToPlay) {…}
private int YouMethodToRun8Tasks(int[][] boardToSearch, int numGamesToPlay)
{
...
var taskList = new List<Task<int[]>>();
// create and run 8 tasks
for(var i = 0; i < 8; i++)
{
// it will capture the parameters and use them in all 8 tasks
taskList.Add(Task.Run<int[]>(() => PlayGames(boardToSearch, numGamesToPlay));
}
// do something else
...
// wait for all tasks
Task.WaitAll(taskList.ToArray());
// do something else
}
在某些情况下可能被称为最干净的方式。
希望对你有所帮助
我很难理解 TPL,我找不到很多关于它的清晰文章。大多数似乎使用带有 lambda 表达式的简单示例。
我有一个 C# 函数
int[] PlayGames(int[][] boardToSearch, int numGamesToPlay) {…}
我想使用 C# 中的 .NET 4.6 TPL 使其可线程化。我想一次启动最多 8 个这些功能,等到它们全部完成,捕获结果并继续。
我似乎无法获得正确的类型并且它没有按预期工作。
这是我目前得到的:
Task<int[]> PlayGames(int[][] boardToSearch, int numGamesToPlay) {…code that takes a long time…}
private int FindBestMove(int[][] boardToSearch, int numGamesToPlay)
{
…
var taskList = new List<Task>();
taskList.Add(Task.Factory.StartNew(() => { return PlayGames(boardToSearch, numGamesToPlay); }));
taskList.Add(Task.Factory.StartNew(() => { return PlayGames(boardToSearch, numGamesToPlay); }));
// Tests
Task a = taskList.First();
var a1 = a.Result; // NOT ALLOWED!? Viewable in debugger, cannot access it.
var b = Task.FromResult(a);
var b1 = b.Result; // Works but cannot access child member Result. Debugger sees it, I can’t!?
Task.WaitAll(taskList.ToArray());
…
}
这是我的问题
如何删除 lambda 表达式
() => { return PlayGames(boardToSearch, numGamesToPlay); }
?我想以某种方式使用Func()
,但我一辈子都不知道怎么说“Task.Factory.StartNew<int[]>(Func(PlayGames(boardToSearch, numGamesToPlay)))
”。为什么我需要使用
StartNew()
?当我执行taskList.Add(PlayGames(int[][] boardToSearch, int numGamesToPlay))
时,它会同步执行!?以这种方式将任务添加到列表的正确语法是什么?我是否需要声明我传递给new Task(Func(PlayGames))
? 之类的某种 Func
当你在执行 Task a = taskList.First() 行后查看变量 a 时,它在调试窗格中清楚地显示了一个名为 Result 的成员。如果我扩展该结果,它包含正确的数据!但是,如果我单击向结果成员添加监视,则会出现错误!如果我这样做 a.Result,编译器会给我同样的错误!??所以调试器说它在那里,但我不能自己查看它!??我可以从对象浏览它但不能直接浏览。我附上了此屏幕截图,以便其他人可以看到。
在远离 lambda 表达式的情况下,使用 .NET 4.6 执行此操作的最简洁方法是什么。我想查看所有类型和声明。
附件是我的调试器的屏幕截图,因此您可以明白我的意思 .Result
让我们从头开始:
1] Func 它只是一个委托,它是 .net 框架库的一部分。
因此,当您传递 () => { return PlayGames(boardToSearch, numGamesToPlay); }
时,这意味着您只是创建了一个类型为 Func<int[]>
的匿名方法。如果将此 lambda 表达式分配给某个变量,则可以检查此类型。
如果你不想使用 lambda,你可以编写一个通用方法并将其放入任务中:Task.Factory.StartNew(YourMethodWhichReturnsIntArray)
.
2] 当您调用 StartNew()
方法时,它只会创建一个新的 Task
并开始执行它。而已。
taskList.Add(PlayGames(int[][] boardToSearch, int numGamesToPlay))
- 这只是将 Task
放入 taskList
。如果在您的 PlayGames
方法中此 Task
未启动,那么您需要稍后再执行此操作。同步与否- 将Task
添加到列表是同步操作,但执行仍然是异步的。任何语法都可能正确或不正确——这取决于复杂性和实现。除了 Task.Factory.StartNew()
,您还可以使用 Task.Run()
方法。它做同样的事情,但以一种更短的方式。并且在传递给 Task
.
3] 我认为这是因为 debugger
有能力等待并行 thread/task 的结果,但 watcher
没有。这就是你得到错误的原因。
所以,我会说不要尝试为并行线程结果添加观察者(只是为了跳过可能的错误)。
4] 在远离 lambda 表达式的情况下,使用 .NET 4.6 执行此操作的最简洁方法是什么。我想查看所有类型和声明。
正如我上面所说,没有必要声明 lambda。您可以创建具有相应定义的方法。但是在这里你将参数传递给这个方法会遇到一些困难(但它们仍然可以解决)。因此,lambda - 是将函数传递给 Task
的最简单方法,因为它可以轻松地从创建这些 lambda 的范围中捕获参数。
What is the cleanest way
- 同样,这取决于。我们每个人都有自己最干净的方式来完成 运行 新任务。所以,我认为(见下文):
// your function
int[] PlayGames(int[][] boardToSearch, int numGamesToPlay) {…}
private int YouMethodToRun8Tasks(int[][] boardToSearch, int numGamesToPlay)
{
...
var taskList = new List<Task<int[]>>();
// create and run 8 tasks
for(var i = 0; i < 8; i++)
{
// it will capture the parameters and use them in all 8 tasks
taskList.Add(Task.Run<int[]>(() => PlayGames(boardToSearch, numGamesToPlay));
}
// do something else
...
// wait for all tasks
Task.WaitAll(taskList.ToArray());
// do something else
}
在某些情况下可能被称为最干净的方式。
希望对你有所帮助