Страницы

Поиск по вопросам

воскресенье, 9 февраля 2020 г.

Создать свой Task.Run

#c_sharp #async #lambda #task


Каким образом в c# можно сделать async получив значение во внешний метод из лямбды?

Вот тестовый пример (он нерабочий):

    public async Task Test(MyClass data)
    {
        return Task.Run(() => {

            MyOtherClass result = null;
            bool endFlag = false;

            protocol.Invoke((MyOtherClass response) => // это async
            {
                endFlag = true;
                result = response;
            }, "uri/to/my/rpc", data);

            for (;;) // а это уже await
            {
                Thread.Sleep(200);
                if (endFlag)
                    break;
            }

            return result;

        });
    }


Задача функции Test - вытащить значение response из лямбды, и вернуть его, причём,
сделать это надо асинхронно, к циклу for(;;) хотелось бы перйти только когда потребуется
await. Подскажите, что нужно сделать, и почему этот код студия ругает?


    


Ответы

Ответ 1



Вероятно, вам надо что то вроде public Task Test(MyClass data) { return Task.Run(async () => { MyOtherClass result = null; bool endFlag = false; protocol.Invoke((MyOtherClass response) => // это async { endFlag = true; result = response; }, "uri/to/my/rpc", data); for (; ; ) // а это уже await { await Task.Delay(200); if (endFlag) break; } return result; }); } Но если вызов protocol.Invoke не блокирующий, то внутренний таск нам не нужен, у нас же уже асинхронный код. public async Task Test(MyClass data) { MyOtherClass result = null; bool endFlag = false; protocol.Invoke((MyOtherClass response) => // это async { result = response; endFlag = true; // И лучше бы флагать о конце операции в конце метода, чтобы не возникло проблем с race condition }, "uri/to/my/rpc", data); for (; ; ) // а это уже await { await Task.Delay(200); if (endFlag) break; } return result; } а вот уже совсем короткий вариант, что делает по сути то же самое public Task Test(MyClass data) { var tcs = new TaskCompletionSource(); protocol.Invoke((MyOtherClass response) => // это async { tcs.SetResult(response); }, "uri/to/my/rpc", data); return tcs.Task; }

Комментариев нет:

Отправить комментарий