繁体   English   中英

这里的ManualResetEvent或ManualResetEventSlim有什么用?

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

我有一个测试,我想确保从async方法获取每个线程的隔离结果。 我的测试如下所示:

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);
    }

测试工作正常,并成功通过。 但是,如果不使用ManualResetEventSlim它也可以按预期工作。 所以我的问题是在此示例中, ManualResetEventSlim的用法是什么? 我真的很困惑吗? 谁能解释在我的测试中使用ManualResetEventSlim与不使用它有什么区别? 我该怎么办,以便不使用ManualResetEvents不会通过我的测试?

Task.WhenAll()仅等待所有任务,直到运行完成。 它将对结果进行排序,使其与传递任务对象的顺序相匹配,但不会强制执行任何顺序,尽管所有Task总是在内部按其出现的顺序启动(请参阅源代码 )。 如果您需要固定的执行顺序,那么您必须亲自处理它,例如使用WaitHandle(如ManualRestEvent或Semaphore)或使用任务继续方法。

这意味着,如果您的任务都同样短暂地运行(例如在您的示例中),则它们的执行顺序相同,而执行顺序相同。 但是,如果您的任务在不同的时间执行,例如task1-> 2000 ms和task2-> 20 ms,则task2将比task1早完成。

或者使用您的示例,当task1花费比task2更长的时间才能调用sut.MyMethod()时 ,结果将是不同的。 现在,如果您需要task1在task2之前完成,则需要控制流程。

暂无
暂无

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

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