Update: поступили замечания по тесту. Мои комментарии:
- Сборка в релизе не дает никакой прибавки к скорости
- Убирание lock (он тут не нужен) дает минимальную прибавку к скорости
- .NET 7 на тесте работает на порядок медленнее, чем .NET 4.8
Написал свой тест, который показал, что ваше предположение о медленной работе в несколько потоков неверно. Результаты работы программы опубликованной ниже:
simple: 00:00:04.2730974, parallel: 00:00:01.6736944, aepot: 00:00:04.3022718
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace ConsoleApp2
{
internal class Program
{
static void Main(string[] args)
{
var swSimple = new Stopwatch();
var swParallel = new Stopwatch();
var swAepot = new Stopwatch();
var random = new Random();
string searchString = new string('0', 100);
var words = new List<string>();
for (int i = 0; i < 5e3; i++)
{
char randomNum = "0123456789"[random.Next(10)];
string sampleString = new string(randomNum, random.Next(100 * i));
words.Add(sampleString);
swSimple.Start();
var list1 = RunSimple(words, searchString);
swSimple.Stop();
swParallel.Start();
var list2 = RunParallel(words, searchString);
swParallel.Stop();
swAepot.Start();
var list3 = RunAepot(words, searchString);
swAepot.Stop();
if (list1.Count != list2.Count || list3.Count != list1.Count)
{
Console.WriteLine($"Функции не идентичны: words={words.Count}, searchString={searchString.Length}, RunSimple: {list1.Count}, RunParallel: {list2.Count}, RunAepot: {list3.Count}");
}
}
Console.WriteLine($"simple: {swSimple.Elapsed}, parallel: {swParallel.Elapsed}, aepot: {swAepot.Elapsed}");
}
static List<string> RunSimple(List<string> words, string searchString)
{
var matchingWords = new List<string>();
foreach (var word in words)
{
if (word.StartsWith(searchString))
{
matchingWords.Add(word);
}
}
return matchingWords;
}
static List<string> RunParallel(List<string> words, string searchString)
{
var matchingWords = new ConcurrentBag<string>();
Parallel.ForEach(words, word =>
{
if (word.StartsWith(searchString))
{
lock (matchingWords)
{
matchingWords.Add(word);
}
}
});
return matchingWords.ToList();
}
static List<string> RunAepot(List<string> words, string searchString)
{
Task<List<string>> task = Task.Run(() =>
{
List<string> result = new List<string>();
foreach (var word in words)
{
if (word.StartsWith(searchString))
{
result.Add(word);
}
}
return result;
});
// здесь можно нарисовать в интерфейсе, что поиск начался
//List<string> filteredWords = await task;
// здесь можно отобразить результат
task.Wait();
return task.Result;
}
}
}