首先,如果我的代码不好或我的描述很差,我想道歉。这是我第一次使用C#线程/任务。我在我的代码中尝试做的是查看列表中的名称和列表中的每个50个名称,启动一个新任务并将这50个名称传递给另一个将执行计算重量级方法的方法。数据。我的代码仅适用于列表中的前50个名称,并且每隔一段时间返回0个结果,我似乎无法弄清楚原因。
public static async void startInitialDownload(string value)
{
IEnumerable<string> names = await Helper.getNames(value, 0);
decimal multiple = names.Count() / 50;
string[] results;
int num1 = 0;
int num2 = 0;
for (int i = 0; i < multiple + 1; i++)
{
num1 = i * 50;
num2 = (50 * (i + 1));
results = names.TakeWhile((name, index) => index >= num1 && index < num2).ToArray();
Task current = Task.Factory.StartNew(() => getCurrentData(results));
await current.ConfigureAwait(false);
}
}
答案 0 :(得分:2)
将可枚举实现到一个列表中,以便计算一次,而不是循环中的每次迭代。您可以使用Skip
和Take
方法获取列表范围:
public static async void startInitialDownload(string value) {
IEnumerable<string> names = await Helper.getNames(value, 0);
List<string> nameList = names.ToList();
for (int i = 0; i < nameList.Count; i += 50) {
string[] results = nameList.Skip(i).Take(50).ToArray();
Task current = Task.Factory.StartNew(() => getCurrentData(results));
await current.ConfigureAwait(false);
}
}
或者您可以将项目添加到列表中,并在其大小合适时执行:
public static async void startInitialDownload(string value) {
IEnumerable<string> names = await Helper.getNames(value, 0);
List<string> buffer = new List<string>();
foreach (string s in names) {
buffer.Add(s);
if (buffer.Count == 50) {
Task current = Task.Factory.StartNew(() => getCurrentData(buffer.ToArray()));
await current.ConfigureAwait(false);
buffer = new List<string>();
}
}
if (buffer.Count > 0) {
Task current = Task.Factory.StartNew(() => getCurrentData(buffer.ToArray()));
await current.ConfigureAwait(false);
}
}
答案 1 :(得分:0)
名称TakeWhile
表示只在条件为真时才接受条目。因此,如果它通过读取条件为假的条目开始,则它永远不需要任何东西。
因此,第一个循环,您从num1
= 0开始。因此,它会从num1
到num2
读取条目。
第二个循环,你开始时num1
为51.所以它再次开始阅读......并且它命中的第一个条目,条件为假,所以它会停止。
您可以尝试使用Where
,或者先使用Skip
。
tl; dr;它:我不认为你的问题与并行任务有任何关系,我认为这是由于使用了错误的LINQ方法来提取你想要使用的名称。
答案 2 :(得分:0)
正如我从Stephen Cleary对类似(但不完全相同)问题的回答中所理解的那样,你不需要在那里使用ConfigureAwait()。
以下是相关链接:on stack overflow
这就是我要做的事情而不是你的for循环的最后两行:
Task.Factory.StartNew(() => getCurrentData(results));
那就是它。通过使用工厂,并且不等待,您将让该任务独立运行(可能在新线程上)。如果您的存储都是线程安全的(请参阅:System.Collections.Concurrent
btw),那么您应该全部设置。
警告:如果你没有向我们展示之后的,那么你的结果可能会有所不同。
答案 3 :(得分:0)
它不是一个直接的解决方案,但可能会有效。
public static IEnumerable<T[]> MakeBuckets<T>(IEnumerable<T> source, int maxSize)
{
List<T> currentBucket = new List<T>(maxSize);
foreach (var s in source)
{
currentBucket.Add(s);
if (currentBucket.Count >= maxSize)
{
yield return currentBucket.ToArray();
currentBucket = new List<T>(maxSize);
}
}
if(currentBucket.Any())
yield return currentBucket.ToArray();
}
稍后您可以遍历MakeBucket函数的结果。