Асинхронные задачи c # - PullRequest
       8

Асинхронные задачи c #

0 голосов
/ 05 ноября 2018

Я пытаюсь понять асинхронное программирование в C #. Я создал пример функции, которая может быть вызвана только один раз. Например, чтение из большого файла. Я хочу создать запрос, и запрос будет ждать в запросе, пока они не смогут безопасно прочитать файл.

AsyncWork aw = new AsyncWork();

Task.Run(() => {
    for (int count = 0; count < 10; count++) {
        aw.DoAsyncWork(count);
        Console.WriteLine("request added");
    }
});
Console.ReadKey();

и AsyncWork

public class AsyncWork {
    int Requests = 0;
    int Workers = 0;

    public AsyncWork() { }

    public async Task DoAsyncWork(int count) {
        Requests++;

        while (Workers > 0) ;

        Workers++;
        Requests--;

        if (Workers > 1) Console.WriteLine("MORE WORKERS AT ONCE");

        Console.WriteLine(count.ToString() + " Started task");
        //reading from file
        await Task.Delay(1000);
        Console.WriteLine(count.ToString() + " Ended task");

        Workers--;
    }
}

Я ожидал, что у меня будет 10 запросов, и тогда они будут выполнены один за другим. Но вывод такой:

0 Started task
request added
0 Ended task
1 Started task
request added
1 Ended task
2 Started task
request added
2 Ended task
3 Started task
request added
3 Ended task
4 Started task
request added
4 Ended task
5 Started task
request added
5 Ended task
6 Started task
request added
6 Ended task
7 Started task
request added
7 Ended task
8 Started task
request added
8 Ended task
9 Started task
request added
9 Ended task

Почему он работает синхронно?

1 Ответ

0 голосов
/ 05 ноября 2018

Когда вы запустите код, ваш первый работник начнет работать, затем следующий застрянет в имеющемся у вас цикле занятости while (Workers > 0) ; и не будет двигаться, пока предыдущий работник не закончит работу. Затем, когда он запустится, следующий рабочий будет застревать там и т. Д. Для каждой итерации цикла, в котором вы запускаете рабочих.

Таким образом, у вас когда-либо есть только один рабочий, выполняющий работу, и один рабочий привязывает весь ЦП, ожидая его завершения.

Правильный способ синхронизировать доступ при написании асинхронного кода - использовать SemaphoreSlim и использовать WaitAsync, что будет асинхронно ждать получения семафора, а не синхронно блокировать поток ( и привязка процессора, пока вы на нем), чтобы другие работники закончили. Он также имеет преимущество в том, что он безопасен для доступа из нескольких потоков, в отличие от целого числа, которое не безопасно для изменения из нескольких потоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...