Ядро ASP.net, как использовать async / await в пустых методах - PullRequest
0 голосов
/ 28 февраля 2019

Я пытаюсь разобраться в асинхронности.Я хотел бы сделать один из моих методов асинхронным, потому что это занимает некоторое время, поэтому я попробовал это:

public static async Task GenerateExcelFile(HashSet<string> codes, ContestViewModel model)
{
    var totalCodeToDistribute = model.NbrTotalCodes - (model.NbrCodesToPrinter + model.NbrCodesToClientService);
    if (model.NbrTotalCodes > 0)
    {
        using (var package = new ExcelPackage())
        {

            await DoStuff(some, variables, here);

            package.SaveAs(fileInfo);
        }
    }
}

, чтобы я мог вызвать его в моем контроллере так:

 await FilesGenerationUtils.GenerateExcelFile(uniqueCodesHashSet, model);

но когда дело доходит до ключевого слова "await", оно говорит, что "Тип void не является ожидаемым"

Это способ ожидания методов void или это не лучший метод?И если это так, что будет лучшим способом сделать это?

РЕДАКТИРОВАТЬ: контроллер:

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Index(ContestViewModel model)
        {
            var contentRootPath = _hostingEnvironment.ContentRootPath;

            DirectoryUtils.OutputDir = new DirectoryInfo(contentRootPath + Path.DirectorySeparatorChar
                                                                         + "_CodesUniques" + Path.DirectorySeparatorChar
                                                                         + model.ProjectName +
                                                                         Path.DirectorySeparatorChar
                                                                         + "_Codes");
            var directory = DirectoryUtils.OutputDir;

            var selectedAnswer = model.SelectedAnswer;

            var uniqueCodesHashSet = new HashSet<string>();

            try
            {

                while (uniqueCodesHashSet.Count < model.NbrTotalCodes)
                {
                    var generatedString = RandomStringsUtils.Generate(model.AllowedChars, model.UniqueCodeLength);
                    uniqueCodesHashSet.Add(generatedString.ToUpper());
                }

                #region FOR TXT FILES

                if (selectedAnswer == FileExtension.TXT.GetStringValue())
                {
                   await FilesGenerationUtils.GenerateTxtFiles(uniqueCodesHashSet, model, directory);
                }

                #endregion

                #region FOR XLSX FILES

                if (selectedAnswer == FileExtension.XLSX.GetStringValue())
                {
                    await FilesGenerationUtils.GenerateExcelFile(uniqueCodesHashSet, model);
                }

                #endregion


                return View();
            }
            catch (Exception ex)
            {
                Console.Write(ex);
            }

            return View();
        }

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

public static Task DoStuff(ExcelWorksheet sheet, HashSet<string> codes, int rowIndex, int count, int maxRowValue)
        {
            foreach (var code in codes)
            {
                sheet.Row(rowIndex);
                sheet.Cells[rowIndex, 1].Value = code;
                rowIndex++;
                count++;
                if (rowIndex == maxRowValue && count < (codes.Count - 1))
                {
                    sheet.InsertColumn(1, 1);
                    rowIndex = 1;
                }
            }
            //What should be returned?!
            return null;
        }

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Вы можете написать асинхронные пустые методы, но их нельзя ожидать:

public static class Program
{
    public static async Task Main()
    {
        const int mainDelayInMs = 500;
        AsyncVoidMethod();
        await Task.Delay(mainDelayInMs);
        Console.WriteLine($"end of {nameof(Main)}");
    }

    static async void AsyncVoidMethod()
    {
        await Task.Delay(1000);
        Console.WriteLine($"end of {nameof(AsyncVoidMethod)}");
    }
}

Как видите, AsyncVoidMethod является асинхронным, но я не могу написать await AsyncVoidMethod();.

Асинхронные пустые методы должны (в большинстве случаев) не будет использоваться, так как вы не можете дождаться завершения задачи, и любое сгенерированное исключение может не обрабатываться (и поэтому может привести к сбою приложения): Почему именно void async плох?

0 голосов
/ 28 февраля 2019

Как правило, притворяться, что ваш метод асинхронный, когда он блокируется под капотом, мало что дает.Если вам нужна задача, вы можете заключить метод блокировки в Task.Run, чтобы создать ожидаемую задачу.Вы по-прежнему будете использовать и блокировать поток, но не текущий.

Рекомендуемое чтение: https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-using.html

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