【问题标题】:How to wait for first async await method before continuing second method in mvc c#?如何在继续 mvc c# 中的第二个方法之前等待第一个异步等待方法?
【发布时间】:2020-03-20 22:49:25
【问题描述】:

我在 mvc c# 中创建了两个方法,使用 async task await 作为第一个操作方法我使用以下代码

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

现在在我的提交上单击此方法在后台运行,并需要一些时间保存在数据库中,另一方面将标志设置为 1 用于下一页,这是我再次使用的一种表单提交

int Flag = await repository.GetFlagStatus(DocumentID);

为了获得标志状态表格我使用的数据库表

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;
        }

现在我的问题是如何等待第二种方法,直到我的第一种方法根据第一种方法的输出将数据库中的数据保存为标志 0 或标志 1。 我用 await Task.Delay(10000);等待第二种方法,但是如果数据在 10 秒之前保存在数据库中,我为什么要等待 10 秒用户会等待它。

因此,为了删除该部分,我使用计时器在 5 秒后检查数据库表行更新,并像这样修改我的代码

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;
                }
            }           
        }

因此,我收到以下错误 我也使用这种方法检查表,但得到同样的错误。

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

System.InvalidOperationException: '在创建模型时不能使用上下文。如果在 OnModelCreating 方法中使用上下文,或者多个线程同时访问同一个上下文实例,则可能会引发此异常。请注意,不保证 DbContext 和相关类的实例成员是线程安全的。'

我希望你能理解我关于如何在异步任务中等待或如何在 5 秒后检查数据库的问题。 提前致谢。

【问题讨论】:

  • 更好的问题,为什么保存数据需要这么长时间?在围绕它进行工程设计之前,您可能希望解决当前的瓶颈。
  • 除了单独线程上的计时器,您还可以使用 Task.Delay 为 1 或 2 秒的循环。循环直到你得到一个值。
  • @gunr2171 更好的问题,为什么保存数据需要这么长时间?看到因为我使用一个 web 服务来发送参数并获得响应,响应需要一些时间,例如 20 秒到 30 秒或更短,并且该响应已保存在数据库中,并且我需要使用该响应加载其他视图。
  • @HansKesting 你能给我一些关于循环延迟的代码吗,因为我已经使用了 await Task.Delay(10000);它等待 10 秒,但我为什么要使用它。我想等到得到响应而不是修复。
  • 不是很清楚你想要达到什么。但是 DbContext 不能在线程之间共享。而且你不应该在 mvc 应用程序中使用 Thread 或 Timer。

标签: c# asp.net-mvc asynchronous timer async-await


【解决方案1】:

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

你不应该在现代代码中使用ThreadThread 唯一剩下的用例是 COM 互操作,您在这里没有这样做。请改用Task

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

除了更小的代码之外,Task 有更好的方法来检测完成和异常。

例如,如果你想异步等待sendData完成,你可以await它:

await sendData;
// SaveCustomerDataAsync has completed now.

【讨论】:

  • 我像你说的那样修改了我的代码,但我不想等到我的第一个呼叫发送响应。我希望它们在后台加载,因为我想加载另一个视图,其中我有一个表单,所以当我收到第一次调用的数据时,我会将这两个数据合并并显示到第三个视图中。
  • 您不必马上await。只需将Task 保存在某处,并在需要回复时将await 保存。
  • 斯蒂芬我标记了你的答案并听取了我使用 do...while 循环来保留第一个响应的建议,当我得到第一个响应时,我将该响应与第二个响应合并。所以谢谢你的帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-01
  • 2017-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多