我正在调查一些奇怪的对象生命周期问题,并遇到了C#编译器的这种非常令人费解的行为:
考虑以下测试类:
class Test
{
delegate Stream CreateStream();
CreateStream TestMethod( IEnumerable<string> data )
{
string file = "dummy.txt";
var hashSet = new HashSet<string>();
var count = data.Count( s => hashSet.Add( s ) );
CreateStream createStream = () => File.OpenRead( file );
return createStream;
}
}
Run Code Online (Sandbox Code Playgroud)
编译器生成以下内容:
internal class Test
{
public Test()
{
base..ctor();
}
private Test.CreateStream TestMethod(IEnumerable<string> data)
{
Test.<>c__DisplayClass1_0 cDisplayClass10 = new Test.<>c__DisplayClass1_0();
cDisplayClass10.file = "dummy.txt";
cDisplayClass10.hashSet = new HashSet<string>();
Enumerable.Count<string>(data, new Func<string, bool>((object) cDisplayClass10, __methodptr(<TestMethod>b__0)));
return new …
Run Code Online (Sandbox Code Playgroud) class A
{
public event EventHandler AEvent;
}
class B
{
private A _foo;
private int _bar;
public void AttachToAEvent()
{
_foo.AEvent += delegate()
{
...
UseBar(_bar);
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
由于delegate
捕获变量this._bar
,它是否隐含地保持实例B
?将B
通过事件处理程序和捕获的变量引用实例A
吗?
如果_bar
是方法的局部变量,它会有所不同AttachToAEvent
吗?
因为在我的情况下,A
生命的实例远远长于并且远小于实例B
,我担心通过这样做导致"内存泄漏".
我正在循环运行并以下列方式开始执行任务:
var iResult = new List<Task>();
foreach(var i in myCollection)
{
var task = Task.Factory.StartNew(() =>
DoSomething(), TaskCreationOptions.LongRunning);
task.ContinueWith(m => myResponseHandler(m.Result));
iResult.Add(task);
}
Run Code Online (Sandbox Code Playgroud)
在我的DoSomething()
方法中,我有一个计时器:
public static myMsg DoSomething()
{
var timer = System.Diagnostics.Stopwatch.StartNew();
DoLongRunningTask(); //If it matters this hits a REST endpoint (https)
timer.Stop();
return new myMsg(timer.ElaspedMilliseconds);
}
Run Code Online (Sandbox Code Playgroud)
当我遍历我的列表时,myMsg
ElaspedMilliseconds似乎完全是加法的 - 第一个上的ElaspedMilliseconds可能是300,但最后一个可能是50000(50秒) - 这实际上是整个事情所需的大致时间运行(由另一个计时器测量).