我一直在使用Task.Factory.FromAsync()方法,並且一直在經歷嚴重的內存泄漏。我用探查它表明,大量的對象似乎只是使用後遊逛:使用Task.Factory.FromAsync時泄漏
Heap shot 140 at 98.591 secs: size: 220177584, object count: 2803125, class count: 98, roots: 666
Bytes Count Average Class name
25049168 142325 175 System.Threading.Tasks.Task<System.Int32> (bytes: +398816, count: +2266)
1 root references (1 pinning)
142324 references from: System.Threading.Tasks.Task
142305 references from: System.Threading.Tasks.TaskCompletionSource<System.Int32>
98309 references from: task_test.Task3Test.<Run>c__AnonStorey1
25049024 142324 176 System.Threading.Tasks.Task (bytes: +398816, count: +2266)
142304 references from: System.Threading.Tasks.TaskContinuation
17078880 142324 120 System.Action<System.Threading.Tasks.Task<System.Int32>> (bytes: +271920, count: +2266)
142324 references from: System.Threading.Tasks.TaskActionInvoker.ActionTaskInvoke<System.Int32>
17076600 142305 120 System.Runtime.Remoting.Messaging.MonoMethodMessage (bytes: +271680, count: +2264)
1 root references (1 pinning)
142304 references from: System.MonoAsyncCall
17076584 142305 119 System.AsyncCallback (bytes: +271920, count: +2266)
1 root references (1 pinning)
142304 references from: System.MonoAsyncCall
17076584 142305 119 System.Func<System.Int32> (bytes: +271920, count: +2266)
1 root references (1 pinning)
142305 references from: System.Func<System.IAsyncResult,System.Int32>
142304 references from: System.Runtime.Remoting.Messaging.AsyncResult
1 references from: System.Func<System.AsyncCallback,System.Object,System.IAsyncResult>
17076584 142305 119 System.Func<System.IAsyncResult,System.Int32> (bytes: +271920, count: +2266)
1 root references (1 pinning)
142305 references from: System.Threading.Tasks.TaskFactory.<FromAsyncBeginEnd>c__AnonStorey3A<System.Int32>
17076480 142304 120 System.Runtime.Remoting.Messaging.AsyncResult (bytes: +271800, count: +2265)
98461 references from: System.Object[]
我試圖找出什麼類型的東西可能/可能不會出現阻止了從識別物體的gc不再被使用。 FromAsync返回一個從TaskCompletionSource獲得的Task對象,該對象具有一個類變量「source」,該變量包含Task從任務調用中獲取的值。
這裏是測試用例。它還包括使用StartNew()的情況,其中內存使用沒有爆炸。下面的初始Test3Task沒有使用ContinueWith,但是看看它是不是我們沒有清理的東西,我們把它放在了(沒有效果)。 [不,下面使用的聆聽變量是多餘的 - 有計劃,使測試更加聰明,但一做永遠是一樣好。]
using System;
using System.Threading;
using System.Threading.Tasks;
namespace task_test
{
class MainClass
{
public static void Main (string[] args)
{
// Test3 - Leaky
var t = new Task3Test();
// Test4 - Doesn't leak
// var t = new Task4Test();
t.Run();
}
}
public class BaseTask
{
public int GetRandomInt(int top)
{
Random random = new Random();
return random.Next(1,top);
}
}
public class FibArgs
{
public byte[] data;
public int n;
}
public class Fib
{
public int Calculate(FibArgs args)
{
int n = args.n;
int a = 0;
int b = 1;
// In N steps compute Fibonacci sequence iteratively.
for (int i = 0; i < n; i++)
{
int temp = a;
a = b;
b = temp + b;
}
Console.WriteLine("ThreadId: {2}, fib({0}) = {1}", n, a, Thread.CurrentThread.GetHashCode());
return a;
}
}
public class Task3Test : BaseTask
{
public void Run()
{
bool listening = true;
long i = 0;
while (listening)
{
i++;
Func<int> fun =() => {
int n = GetRandomInt(100);
Fib f = new Fib();
FibArgs args = new FibArgs();
args.n = n;
return f.Calculate(args);
};
var t = Task<int>.Factory.FromAsync(fun.BeginInvoke, fun.EndInvoke, null);
t.ContinueWith(x => {
if (x.IsCompleted) {
x.Dispose();
x = null;
}
}
);
}
}
}
public class Task4Test : BaseTask
{
public void Run()
{
bool listening = true;
long i = 0;
while (listening)
{
int n = GetRandomInt(100);
Fib f = new Fib();
FibArgs args = new FibArgs();
args.n = n;
Task.Factory.StartNew(() => f.Calculate(args), TaskCreationOptions.LongRunning)
.ContinueWith(x => {
if(x.IsFaulted)
{
Console.WriteLine("OOPS, error!!!");
x.Exception.Handle(_ => true); //just an example, you'll want to handle properly
}
else if(x.IsCompleted)
{
Console.WriteLine("Cleaning up task {0}", x.Id);
x.Dispose();
}
}
);
}
}
}
}
我在Darwin/x86上使用SGen運行此操作,幾分鐘後內存使用情況非常穩定。然而,Boehm,它迅速升高。你在哪個平臺上使用哪種GC? – 2013-05-08 17:10:37
我的同事和我在Ubuntu 12.04 64位上測試了類似的東西,並且看到了與GC相似的行爲。 – 2013-05-08 18:55:09
同時運行。使用sgen獲得堆積,並且它在瞬間完成記憶。 – 2013-05-08 18:59:10