启动一个执行委托的新进程

时间:2021-08-27 00:25:05

Is is possible in .NET to execute a method (delegate, static method, whatever) in a child process? System.Diagnostics.Process seems to require an actual filename, meaning that a separate executable is needed.

在.NET中是否可以在子进程中执行方法(委托,静态方法,等等)? System.Diagnostics.Process似乎需要一个实际的文件名,这意味着需要一个单独的可执行文件。

What I am trying to do is to verify, in a unit test, that an OS resource is cleaned up on process exit. I know that could use CodeDOM or IL generation to create such an assembly and execute it, but the whole point of unit tests is to isolate component parts, not to create complexity. For the same reason, I'd like to avoid a separate assembly altogether.

我要做的是在单元测试中验证在进程退出时是否清理了OS资源。我知道可以使用CodeDOM或IL生成来创建这样的程序集并执行它,但单元测试的重点是隔离组件,而不是创建复杂性。出于同样的原因,我想完全避免单独的集会。

Ideally, I would do something like:

理想情况下,我会做类似的事情:

public static void CreateCounter()
{
    var counter = new PerformanceCounter("category", "counter", "instance");
    counter.InstanceLifetime = PerformanceCounterInstanceLifetime.Process;
}

[Test]
public void TestResourceDisposal()
{
    // Start child process to execute CreateCounter()
    ...
    // verify the resource is disposed
}

3 个解决方案

#1


6  

First of all, no, there's no way to do this. I process implies a .exe. This isn't Unix where you can fork a process that's a copy of the parent.

首先,不,没有办法做到这一点。我处理意味着.exe。这不是Unix,您可以在其中分叉一个父进程副本的进程。

I'd just create a tiny .exe to run. Do you need to run the test with different performance counters? If it works with one, then surely it will work with any of them?

我只是创建一个小的.exe来运行。您是否需要使用不同的性能计数器运行测试?如果它适用于一个,那么它肯定会与它们中的任何一个一起使用吗?

#2


2  

What you are talking about is not a unit test. Interacting with actual (expensive) operating system services violates the basic principle of isolation that unit tests are meant to strive for.

你所说的不是单元测试。与实际(昂贵的)操作系统服务交互违反了单元测试旨在争取的基本隔离原则。

If your intent is to test the code in a more end-to-end fashion, actually interacting with the performance counter and so on, this would be an integration test and should be written in a more "heavy duty" way, i.e. writing a separate EXE if needed, running any complex setup or cleanup steps, etc.

如果你的目的是以更端对端的方式测试代码,实际上与性能计数器等进行交互,这将是一个集成测试,应该以更“重型”的方式编写,即编写一个如果需要,单独的EXE,运行任何复杂的设置或清理步骤等。

If you need to unit test the components that deal with the performance counter, you must first abstract this dependency away. Generally you would create a base class or interface representing the surface area of the performance counter and then create a test double of some sort to replace its functionality at (test) runtime. The real system would use a simple wrapper that delegates to the actual performance counter and would be exercised by integration tests as above.

如果需要对处理性能计数器的组件进行单元测试,则必须先将此依赖关系抽象出去。通常,您将创建一个表示性能计数器表面区域的基类或接口,然后创建某种类型的测试双,以替换(test)运行时的功能。真实系统将使用一个简单的包装器,该包装器委托给实际的性能计数器,并将通过上面的集成测试来执行。

From reading your comment above, it almost sounds like you are trying to test a guarantee of the .NET framework. I would question whether this is actually necessary as it is quite well tested already, although maybe you want to test that your code is using it properly (in which case you could either do unit or integration testing depending on the verification you are seeking).

通过阅读上面的评论,几乎听起来你正试图测试.NET框架的保证。我会怀疑这是否真的有必要,因为它已经经过了很好的测试,尽管你可能想要测试你的代码是否正确使用它(在这种情况下你可以根据你正在寻求的验证进行单元测试或集成测试)。

#3


0  

I'm not sure exactly what you're trying to accomplish, but would it be easier to return the performance counter instance from CreateCounter and use a using directive since a PerformanceCounter is IDisposable. Like this:

我不确定你要完成什么,但是从CreateCounter返回性能计数器实例并使用using指令会更容易,因为PerformanceCounter是IDisposable。像这样:

using (var counter = CreateCounter())
{
     // Do some work
}

Then the counter will always be cleaned up, even if you throw during the test.

然后,即使您在测试期间投掷,计数器也将始终被清理干净。

Otherwise, I think what you want is to create a new thread. You can then you thread.Join() to wait for the thread to complete. See the System.Threading namespace for more info.

否则,我认为你想要的是创建一个新线程。然后你可以使用thread.Join()来等待线程完成。有关详细信息,请参阅System.Threading命名空间。

#1


6  

First of all, no, there's no way to do this. I process implies a .exe. This isn't Unix where you can fork a process that's a copy of the parent.

首先,不,没有办法做到这一点。我处理意味着.exe。这不是Unix,您可以在其中分叉一个父进程副本的进程。

I'd just create a tiny .exe to run. Do you need to run the test with different performance counters? If it works with one, then surely it will work with any of them?

我只是创建一个小的.exe来运行。您是否需要使用不同的性能计数器运行测试?如果它适用于一个,那么它肯定会与它们中的任何一个一起使用吗?

#2


2  

What you are talking about is not a unit test. Interacting with actual (expensive) operating system services violates the basic principle of isolation that unit tests are meant to strive for.

你所说的不是单元测试。与实际(昂贵的)操作系统服务交互违反了单元测试旨在争取的基本隔离原则。

If your intent is to test the code in a more end-to-end fashion, actually interacting with the performance counter and so on, this would be an integration test and should be written in a more "heavy duty" way, i.e. writing a separate EXE if needed, running any complex setup or cleanup steps, etc.

如果你的目的是以更端对端的方式测试代码,实际上与性能计数器等进行交互,这将是一个集成测试,应该以更“重型”的方式编写,即编写一个如果需要,单独的EXE,运行任何复杂的设置或清理步骤等。

If you need to unit test the components that deal with the performance counter, you must first abstract this dependency away. Generally you would create a base class or interface representing the surface area of the performance counter and then create a test double of some sort to replace its functionality at (test) runtime. The real system would use a simple wrapper that delegates to the actual performance counter and would be exercised by integration tests as above.

如果需要对处理性能计数器的组件进行单元测试,则必须先将此依赖关系抽象出去。通常,您将创建一个表示性能计数器表面区域的基类或接口,然后创建某种类型的测试双,以替换(test)运行时的功能。真实系统将使用一个简单的包装器,该包装器委托给实际的性能计数器,并将通过上面的集成测试来执行。

From reading your comment above, it almost sounds like you are trying to test a guarantee of the .NET framework. I would question whether this is actually necessary as it is quite well tested already, although maybe you want to test that your code is using it properly (in which case you could either do unit or integration testing depending on the verification you are seeking).

通过阅读上面的评论,几乎听起来你正试图测试.NET框架的保证。我会怀疑这是否真的有必要,因为它已经经过了很好的测试,尽管你可能想要测试你的代码是否正确使用它(在这种情况下你可以根据你正在寻求的验证进行单元测试或集成测试)。

#3


0  

I'm not sure exactly what you're trying to accomplish, but would it be easier to return the performance counter instance from CreateCounter and use a using directive since a PerformanceCounter is IDisposable. Like this:

我不确定你要完成什么,但是从CreateCounter返回性能计数器实例并使用using指令会更容易,因为PerformanceCounter是IDisposable。像这样:

using (var counter = CreateCounter())
{
     // Do some work
}

Then the counter will always be cleaned up, even if you throw during the test.

然后,即使您在测试期间投掷,计数器也将始终被清理干净。

Otherwise, I think what you want is to create a new thread. You can then you thread.Join() to wait for the thread to complete. See the System.Threading namespace for more info.

否则,我认为你想要的是创建一个新线程。然后你可以使用thread.Join()来等待线程完成。有关详细信息,请参阅System.Threading命名空间。