Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 同步运行GC.Collect_.net_Nunit_Garbage Collection - Fatal编程技术网

.net 同步运行GC.Collect

.net 同步运行GC.Collect,.net,nunit,garbage-collection,.net,Nunit,Garbage Collection,GC.Collect在后台线程中启动垃圾收集,然后立即返回。如何同步运行GC.Collect——即等待垃圾收集完成 这是在NUnit测试的上下文中进行的。我尝试将该设置添加到测试程序集的app.config文件中,并在nunit.exe.config中尝试了相同的设置。两者都没有任何效果——当我调试时,我仍然可以看到终结器在“GC终结器线程”上运行,而不是在调用GC.Collect(NUnit的“TestRunnerThread”)的线程上运行,并且两个线程同时运行 背景:如果测试泄漏(不调用D

GC.Collect
在后台线程中启动垃圾收集,然后立即返回。如何同步运行
GC.Collect
——即等待垃圾收集完成

这是在NUnit测试的上下文中进行的。我尝试将该设置添加到测试程序集的app.config文件中,并在nunit.exe.config中尝试了相同的设置。两者都没有任何效果——当我调试时,我仍然可以看到终结器在“GC终结器线程”上运行,而不是在调用
GC.Collect
(NUnit的“TestRunnerThread”)的线程上运行,并且两个线程同时运行


背景:如果测试泄漏(不调用Dispose)特定类,我希望测试失败。因此,我向该类添加了一个终结器,它设置了一个静态
wasleek
标志;然后,我的test TearDown调用
GC.Collect()
,然后在
wasleek
为true时抛出。但它并不是决定性地失败,因为当它读取
wasleek
时,终结器通常还没有被调用。(垃圾收集最终完成后,它会失败。)

您可以使用
GC.RegisterForFullGCNotification
,使用
GC.Collect(GC.MaxGeneration)
触发完全收集,然后使用
GC.WaitForFullGCComplete
GC.WaitForPendingFinalizers
方法,但请确保仅在测试中使用此选项,它们不应用于生产代码。

更简单/更好的方法是使用模拟并检查显式调用Dispose的预期

使用Rhinomock的示例

public void SomeMethodTest()
{
     var disposable = MockRepository.GenerateMock<DisposableClass>();

     disposable.Expect( d => d.Dispose() );

     // use constructor injection to pass in mock `DisposableClass` object
     var classUnderTest = new ClassUnderTest( disposable ); 

     classUnderTest.SomeMethod();

     disposable.VerifyAllExpectations();
}
public void SomeMethodTest()
{
var disposable=MockRepository.GenerateMock();
Expect(d=>d.Dispose());
//使用构造函数注入传递模拟的'DisposableClass'对象
var classUnderTest=新的classUnderTest(一次性);
classUnderTest.SomeMethod();
一次性。验证所有预期();
}
如果该方法需要创建并处理对象,那么我将使用并注入一个能够创建模拟对象的工厂类。下面的示例使用工厂上的存根,因为它不是我们在本测试中测试的对象

public void SomeMethod2Test()
{
     var factory = MockRepository.Stub<DisposableFactory>();
     var disposable = MockRepository.GenerateMock<DisposableClass>();

     factory.Stub( f => f.CreateDisposable() ).Return( disposable );         
     disposable.Expect( d => d.Dispose() );

     // use constructor injection to pass in mock factory
     var classUnderTest = new ClassUnderTest( factory ); 

     classUnderTest.SomeMethod();

     disposable.VerifyAllExpectations();
}
public void SomeMethod2Test()
{
var factory=MockRepository.Stub();
var disposable=MockRepository.GenerateMock();
factory.Stub(f=>f.CreateDisposable()).Return(一次性);
Expect(d=>d.Dispose());
//使用构造函数注入在模拟工厂中传递
var classUnderTest=新classUnderTest(工厂);
classUnderTest.SomeMethod();
一次性。验证所有预期();
}

无论是否使用并发GC,终结器始终在单独的线程上运行。如果要确保已运行终结器,请尝试使用GC.WaitForPendingFinalizers。

终结器在专用的高优先级后台线程上运行。从你文章的背景来看,我想你可以简单地做到

GC.Collect();
GC.WaitForPendingFinalizers();

Collect()
将安排任何非根实例进行终结,然后线程将等待终结器线程完成

这是一种很好的测试确定性发布的方法,但不能测试终结器代码是否正常工作。因此,Joe可能希望使用这两种方法,具体取决于他希望测试的内容。我知道这是为了确保他的所有类都称为Dispose(第3段)。Dispose模式使用受保护的(虚拟)Dispose(bool disposing)方法,并由IDIsposable调用。Dispose with disposing=true和终结器(如果需要)调用带=假。因此,我不确定Dispose的代码路径是什么意思。如果目的是测试Disposed是否被调用,那么这可能是一个好方法。但是,如果您想测试对象是否符合垃圾收集的条件,那么仅仅知道它们已经被处置是没有用的。完全可以挂起对已处理对象的引用,而不会立即产生不良影响(如果没有使用它们),但这样做意味着内存泄漏,这可能是服务器中的一个严重问题。虽然我怀疑内存分析器是我们对付这一问题的最佳工具,但我对任何试图找到使其可测试的方法的努力表示赞赏。:)医生说WaitForFullGCApproach和WaitForFullGCComplete应该总是一起使用。当我显式地触发GC时,如何等待GC方法?你有这样的代码示例吗?很抱歉回答得太晚了。这里有一个很好的解释和示例,应该或多或少适用于您的代码:您可能希望选择您的方法通知限制,以便基本上立即得到通知。完美!这正是我想要的。谢谢