我现在用TPL类替换我的旧并行化辅助类。当动作代码中出现错误时,我的旧代码已被证明非常不可靠,而且它似乎不是为我现在正在做的事情而构建的。
第一份工作清单很容易翻译成Parallel.ForEach
。但是这里有一个嵌套的索引循环,我无法轻易解决。
int streamIndex = 0;
foreach (var playlist in selectedPlaylists)
{
var localPlaylist = playlist;
foreach (var streamFile in playlist.StreamFiles)
{
var localStreamFile = streamFile;
var localStreamIndex = streamIndex++;
// Action that uses localPlaylist, localStreamFile and localStreamIndex
...
// Save each job's result to its assigned place in the list
lock (streamsList)
{
streamsList[localStreamIndex] = ...;
}
}
}
当共享foreach迭代变量时,局部变量用于正确的闭包支持。
我在考虑像
这样的东西selectedPlaylists.SelectMany(p => p.StreamFiles)
然后我失去了每个streamFile来自哪里的关联,以及应该是确定性的索引,因为它用于在结果列表中对结果进行排序。有没有办法保持这些与Linq的关联,并在枚举列表时添加该计数器?也许像这样(伪造的伪代码):
selectedPlaylists
.SelectMany(p => new
{
Playlist = p,
StreamFile = ~~each one of p.StreamFiles~~,
Index = ~~Counter()~~
})
我可以保留那些旧的嵌套foreach循环并收集列表中的所有作业,然后使用Parallel.Invoke,但这似乎比它需要的更复杂。我想知道是否有一个我还不知道的简单的Linq功能。
答案 0 :(得分:2)
你可以做这样的事......
//
Dictionary<int, object> streamsList = new Dictionary<int, object>();
// First create a composition that holds the playlist and the streamfile
selectedPlaylists.SelectMany(playList => playList.StreamFiles.Select(streamFile => new { PlayList = playList, StreamFile = streamFile }))
// thenfor all of theese add the respective index
.Select((composition, i) => new { StreamFile = composition.StreamFile, PlayList = composition.PlayList, LocalStreamIndex = i })
.AsParallel()
.WithCancellation(yourTokenGoesHere)
.WithDegreeOfParallelism(theDegreeGoesHere)
.ForAll(indexedComposition =>
{
object result =somefunc(indexedComposition.LocalStreamIndex, indexedComposition.PlayList, indexedComposition.StreamFile);;
lock(streamsList) // dont call the function insde the lock or the as parallel is useless.
streamsList[indexedComposition.LocalStreamIndex] = result;
});
答案 1 :(得分:1)
要展开StreamFiles
并与PlayList
保持关联并为其编制索引,您可以使用此查询:
int index = 0;
var query = selectedPlaylists
.SelectMany(p => p.StreamFiles
.Select(s =>
new {
PlayList = p,
Index = index++,
StreamFile = s
}));