简体   繁体   English

这里的ManualResetEvent或ManualResetEventSlim有什么用?

[英]What is the usage of ManualResetEvent or ManualResetEventSlim here?

I have a test and I want to make sure that I will get isolated result per Thread from an async method. 我有一个测试,我想确保从async方法获取每个线程的隔离结果。 My test is look like the following: 我的测试如下所示:

public async Task MyMethod_Concurrency_ReturnsIsolatedResultPerThread()
{
    int expectedResult = 20;

    var theMock = new Mock<IService>();
        theMock.Setup(m => m.GetResult(It.IsAny<int>()))
            .Callback(() => Thread.Sleep(10))
            .Returns<int>(t => Task.FromResult(expectedResult));

        var sut = new MyClass(30, theMock.Object);

        var rs1 = new ManualResetEventSlim();
        var rs2 = new ManualResetEventSlim();

        var task1 = Task.Run(async () =>
        {
            expectedResult = 40;
            await sut.MyMethod();
            rs2.Set();
            rs1.Wait();
            Assert.AreEqual(expectedResult, sut.Result);
        });

        var task2 = Task.Run(async () =>
        {
            rs2.Wait();
            expectedResult = 45;
            await sut.MyMethod();
            Assert.AreEqual(expectedResult, sut.Result);
            rs1.Set();
        });

        var task3 = Task.Run(() => Assert.AreEqual(0, sut.Amount));

        await Task.WhenAll(task1, task2, task3);
    }

The test works fine and passed successfully. 测试工作正常,并成功通过。 However without using ManualResetEventSlim it also works as expected. 但是,如果不使用ManualResetEventSlim它也可以按预期工作。 So my question is what is the usage of ManualResetEventSlim in this example? 所以我的问题是在此示例中, ManualResetEventSlim的用法是什么? I'm really confused with that? 我真的很困惑吗? Can anybody please explain what is difference between using ManualResetEventSlim or not using it in my test? 谁能解释在我的测试中使用ManualResetEventSlim与不使用它有什么区别? What can I do, so that my test won't be passed without using ManualResetEvents ?? 我该怎么办,以便不使用ManualResetEvents不会通过我的测试?

Task.WhenAll() does only wait for all tasks until run to completion. Task.WhenAll()仅等待所有任务,直到运行完成。 It will order the results to match the order the task objects were passed, but it does not enforce any order of execution although all Tasks are always internally started in their occurring order (see source code ). 它将对结果进行排序,使其与传递任务对象的顺序相匹配,但不会强制执行任何顺序,尽管所有Task总是在内部按其出现的顺序启动(请参阅源代码 )。 If you need a fixed execution order than you must take care of it yourself eg by using a WaitHandle like ManualRestEvent or a Semaphore or using the task continuation methods. 如果您需要固定的执行顺序,那么您必须亲自处理它,例如使用WaitHandle(如ManualRestEvent或Semaphore)或使用任务继续方法。

This means if your tasks are all equally short running (like in your example) than they are started in the same order and complete in the same order. 这意味着,如果您的任务都同样短暂地运行(例如在您的示例中),则它们的执行顺序相同,而执行顺序相同。 But if your tasks execute in different times, eg task1 -> 2000 ms and task2 -> 20 ms, than task2 would complete long before task1. 但是,如果您的任务在不同的时间执行,例如task1-> 2000 ms和task2-> 20 ms,则task2将比task1早完成。

Or to use your example when task1 takes longer than task2 to reach the invocation of sut.MyMethod() the result won't be the same. 或者使用您的示例,当task1花费比task2更长的时间才能调用sut.MyMethod()时 ,结果将是不同的。 Now if you need task1 to complete before task2 you need to control the flow. 现在,如果您需要task1在task2之前完成,则需要控制流程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM