I'm trying to get into the asynchronous thing. I'd like to make one of my methods asynchronous because it takes a while to finish so I tried this:
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);
}
}
}
So I could call it in my controller like that:
await FilesGenerationUtils.GenerateExcelFile(uniqueCodesHashSet, model);
but when it comes to the "await" keyword, it says that "Type void is not awaitable"
Is that a way to await for void methods or is it not a best practice? And if so, what would be the best way to do it?
The controller:
[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();
}
If I've understood what you're all saying, I must create a method that would be awaitable. Am I going right if I go with something like this:
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;
}
You can write async void methods but these cannot be awaited:
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)}");
}
}
As you can see AsyncVoidMethod is async but I cannot write await AsyncVoidMethod();
.
Async void methods should (most of the time) not be used as you cannot wait for completion of the task and any exception thrown may not be handled(and so it can crash your application): Why exactly is void async bad?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With