Search code examples
c#asp.net-mvcasynchronoustimerasync-await

How to wait for first async await method before continuing second method in mvc c#?


I created two method in mvc c# using async task await for first action method I use following code

Thread sendData = new Thread(async () => await SaveCustomerDataAsync(DocumentID, DocumentType, bytes, fileName));
sendData.Start();

Now on my submit click this method runs in background and take some time to save in database with flag set to 1 on other-hand for next page which is kind of form submit I again use

int Flag = await repository.GetFlagStatus(DocumentID);

and for getting flag status form database table I use

public int GetFlagStatus(string documentID)
        {          
            var obj = (from a in db.StdPortals
                             select new StdPortalsVM
                             {
                                 DocumentID = a.DocumentID,
                                 Flag = a.Flag,
                             }).Where(x => x.DocumentID == documentID).FirstOrDefault();
          var  result = Convert.ToInt32(obj.Flag);
            return result;
        }

Now my question is that how to wait for second method until my first method save data in database as flag 0 or flag 1 according to out put of first method. I used await Task.Delay(10000); to await second method but why should i wait for 10s if data save in database before 10s user will wait for it.

So, to remove that part I use timer to check database table row update after 5 sec and I modify my code like this

System.Threading.Timer Timer;
        System.DateTime StopTime;       
        public void Run(string documentId)
        {
            StopTime = System.DateTime.Now.AddMinutes(2);
            Timer = new System.Threading.Timer(TimerCallback, documentId, 0, 5000);      
        }
        private void TimerCallback(object state)
        {           
            if (System.DateTime.Now >= StopTime)
            {
                Timer.Dispose();
                return;              
            }
            else
            {
               var obj = (from a in db.StdPortals
                             select new StdPortalsVM
                             {
                                 DocumentID = a.DocumentID,
                                 Flag = a.Flag,
                             }).Where(x => x.DocumentID == documentID).FirstOrDefault();          
                if (obj != null)
                {
                    Timer.Dispose();
                    return;
                }
            }           
        }

So for this I am getting following error I also use this method to check table but getting same error.

bool obj = db.StdPortals.Any(u => u.DocumentID == state.ToString())

System.InvalidOperationException: 'The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.'

I hope you understand my queries that how to wait in async task or how to check database after 5 second. Thanks in advance.


Solution

  • Thread sendData = new Thread(async () => await SaveCustomerDataAsync(DocumentID, DocumentType, bytes, fileName)); sendData.Start();

    You shouldn't use Thread in modern code; the only remaining use case for Thread is COM interop, which you're not doing here. Use Task instead:

    Task sendData = Task.Run(async () => await SaveCustomerDataAsync(DocumentID, DocumentType, bytes, fileName));
    

    In addition to being smaller code, the Task has much nicer ways to detect completion and exceptions.

    For example, if you want to asynchronously wait for sendData to complete, you can just await it:

    await sendData;
    // SaveCustomerDataAsync has completed now.