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

发布于 2024-10-25 05:08:34 字数 617 浏览 1 评论 0原文

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

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

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

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
}

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.

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.

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
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

離殇 2024-11-01 05:08:34

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

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

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.

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?

雨落□心尘 2024-11-01 05:08:34

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

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

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

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

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.

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.

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).

辞旧 2024-11-01 05:08:34

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

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

那么计数器将始终被清理,即使您在测试期间抛出。

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

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:

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文