Какое здесь используется ManualResetEvent или ManualResetEventSlim? - PullRequest
0 голосов
/ 19 мая 2018

У меня есть тест, и я хочу убедиться, что я получу изолированный результат для потока из метода 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 ??

1 Ответ

0 голосов
/ 19 мая 2018

Task.WhenAll () только ждет всех задач, пока не завершится их выполнение.Он упорядочит результаты так, чтобы они соответствовали порядку, в котором были переданы объекты задачи, но он не предписывает какой-либо порядок выполнения, хотя все задачи всегда внутренне запускаются в порядке их появления (см. исходный код ).Если вам нужен фиксированный порядок выполнения, вы должны позаботиться о нем сами, например, используя WaitHandle, такой как ManualRestEvent или Semaphore, или используя методы продолжения задачи.

Это означает, что все ваши задачи выполняются одинаково быстро (например,в вашем примере) чем они запускаются в том же порядке и завершаются в том же порядке.Но если ваши задачи выполняются в разное время, например, task1 -> 2000 мс и task2 -> 20 мс, тогда task2 завершится задолго до task1.

Или использовать ваш пример, когда задача 1 занимает больше времени, чем задача 2, чтобы достичь вызова sut.MyMethod () результат не будет таким же.Теперь, если вам нужно выполнить задачу 1 до выполнения задачи 2, вам нужно контролировать поток.

...