我正在使用一個內存飢渴的應用程序,它使Task的使用能夠並行處理。問題是它產生了大量的內存,然後掛在它上面,使我的16GByte系統超載,直到GC運行。在這一點上,它的表現非常糟糕,可能需要幾天時間才能完成。原始應用程序通常需要30分鐘才能運行。這是這一個精簡版:內存飢餓的多線程應用程序
class Program
{
static void Main(string[] args)
{
var tasks = new List<Task<string[]>>();
var report = new List<string>();
for (int i = 0; i < 2000; i++)
{
tasks.Add(Task<string[]>.Factory.StartNew(DummyProcess.Process));
}
foreach (var task in tasks)
{
report.AddRange(task.Result);
}
Console.WriteLine("Press RETURN...");
Console.ReadLine();
}
}
這裏的「處理器」:
public static class DummyProcess
{
public static string[] Process()
{
var result = new List<string>();
for (int i = 1; i < 10000000; i++)
{
result.Add($"This is a dummy string of some length [{i}]");
}
var random = new Random();
var delay = random.Next(100, 300);
Thread.Sleep(delay);
return result.ToArray();
}
}
我相信這個問題是在這裏:
foreach (var task in tasks)
{
report.AddRange(task.Result);
}
任務沒有得到處置當他們完成時 - 獲取結果(字符串[])離開任務然後處置任務的最佳方式是什麼?
我也試試這個:
foreach (var task in tasks)
{
report.AddRange(task.Result);
task.Dispose();
}
但是沒有太大的區別。我可能會嘗試的是簡單地停止返回的結果,這樣巨大的10 - 50 MB字符串不會被保留(在原始應用程序中)。
編輯:我想更換代碼如下讀取結果:
while (tasks.Any())
{
var listCopy = tasks.ToList();
foreach (var task in listCopy)
{
if (task.Wait(0))
{
report.AddRange(task.Result);
tasks.Remove(task);
task.Dispose();
}
}
Thread.Sleep(300);
}
我有兩個小時後放棄 - 我會讓它運行整夜今晚,看看它是否完成。內存使用似乎更好,但仍然很慢。