1. 程式人生 > 其它 >記一次 ABP VNext 程序崩潰。錯誤源 System.ObjectDisposedException: Cannot access a disposed context instance.

記一次 ABP VNext 程序崩潰。錯誤源 System.ObjectDisposedException: Cannot access a disposed context instance.

正在做 excel 匯入功能,程式碼在自己的機器上正常執行,部署到 CentOS 後只要呼叫這塊程式碼程序就直接崩掉,以下是主要程式碼(有問題):

using (var stream = new MemoryStream())
{
     ImportQuestionsFile.CopyTo(stream);
     var dt = NPOIHelper.ImportExceltoDt(stream);
     var list = new List<CreateUpdateQuestionDto>();
     dt.AsEnumerable().ToList().ForEach(x =>
     {
        ...MORE CODE...
        list.Add(question);
     });
     _questionAppService.InsertManyAsync(list);
     return NoContent();
}

開始以為和以前一樣是程序佔用記憶體太大導致,結果一頓排查程序不是被系統 kill 的。
Logs 裡面又沒有日誌,幸好使用了 Supervisor 守護程序,在它的日誌裡面找到的問題根源:

Unhandled exception. System.ObjectDisposedException: Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'AssociationDbContext'.
   at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()
   at Microsoft.EntityFrameworkCore.DbContext.get_ContextServices()
   at Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker()
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.OnTracked(InternalEntityEntry internalEntityEntry, Boolean fromQuery)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.FireStateChanged(EntityState oldState)

根據日誌分析發現是 DbContext 被 disposed ,唯一可能的就是 using 語句。最後排查是因為 _questionAppService.InsertManyAsync(list); 這個非同步方法沒有加 await 程式就不會等待,uisng 中的程式碼提前結束了。但不知道為啥程序會崩潰。