I have two async functions.
WriteActionToActionLog
- documents action to log
- add rows to db
- async save
SaveSetting
- update rows in db.
- pulls two rows by async list
- update them by simple logic
- save with async.
Both are async. Wrapped with transaction. Adding both tasks to task array. Using whenAll
.
To reduce amount of code I will write /*logic*/
.
Meanwhile I wrote it synced, since the delay is minor, but is seems to me way more correct using parallel tasks.
tried to use waitAll
instead of whenAll
. but answer did not return.
tried to convert the async list within the SaveSetting
function to synced. got the same error
.NET Framework is 4.6.1
public async Task<myObject> wrapperFunc(InnerServiceSettings clientSettings) {
DbModel DB = new DbModel();
using (var transaction = DB.Database.BeginTransaction())
{
try
{
var tasks = new List<Task>();
/*logic - typeActionList created */
var settingsTask = SettingsManager.SaveSetting(DB, clientSettings);
tasks.Add(settingsTask);
var logTask = AdminManager.WriteActionToActionLog(DB, typeActionList, clientSettings.idNum);
tasks.Add(logTask);
Task[] taskArr = tasks.ToArray();
await Task.WhenAll(logTask, settingsTask); //exception thrown
transaction.Commit();
/*logic*/
}
catch(exception ex) {... rollback etc...}
}
}
public async static Task<bool> SaveSetting(DbModel iDb, ClientSettings iSettings)
{
//list to be updated at db. One pull from db instead of several pulls. Also tried to made its sync, leaving save async.
//will return two rows from DB
var objListToChange = await iDb.Settings.Where(x => … ).ToListAsync();
/*logic*/
if (..)
{
var rowAtoUpdate = objListToChange.Where(x => …).FirstOrDefault();
rowAtoUpdate.return_day = (short)iSettings.return_dayA;
}
if (…)
{
var rowBtoUpdate = objListToChange.Where(…).FirstOrDefault();
rowBtoUpdate.return_day = (short)iSettings.return_dayB;
}
try
{
var x = await iDb.SaveChangesAsync();
return true;
}
catch (Exception e)
{
throw e;
}
}
public async static Task<bool> WriteActionToActionLog(DbModel iDb, List<Tuple<int, int>> iActionTypeValue, int iManagerIdNum)
{
var ActionListToAdd = new List<ManagersActionLog>();
foreach(var tupElem in iActionTypeValue)
{
ActionListToAdd.Add(new ManagersActionLog
{
ActionType = tupElem.Item1,
ActionValue = tupElem.Item2,
LogDate = DateTime.Now,
ManagerId = iManagerIdNum,
});
}
try {
iDb.ManagersActionLog.AddRange(ActionListToAdd);
var ans = await iDb.SaveChangesAsync();
return true;
}
catch(Exception ex) {
throw ex;
}
}
Once whenAll
is reached I am getting:
A second operation started on this context before a previous asynchronous operation completed. Use await
to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.