提问者:小点点

调用任务函数发送电子邮件时,对象引用未设置为对象的实例


null

private ApplicationSignInManager _signInManager;
        private ApplicationUserManager _userManager;
        private ApplicationDbContext userDB;
        public ApplicationUserManager UserManager
        {
            get
            {
                return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                _userManager = value;
            }
        }

        public async Task SendEmail(string user_id, string subject, string user_email )
        {
            await UserManager.SendEmailAsync(user_id, subject, user_email);
        }

public ActionResult Transfer(int id, int nurse_id, int ambulance_id, int driver_id, int nurse_account_id)
        {
            Call call = db.Calls.Find(id);

            if(call.amb_id != null)
            {
                Ambulance prev_amb = db.Ambulances.Find(call.amb_id);
                prev_amb.ambulance_status = "FREE";
                db.Entry(prev_amb).State = EntityState.Modified;
            }

            call.call_status = db.Call_Status.Where(m => m.name == "ΣΕ ΑΝΤΑΠΟΚΡΙΣΗ").Select(m => m.call_status_id).First();
            call.nurse_id = nurse_id;
            call.nurse_account_id = nurse_account_id;
            call.amb_id = ambulance_id;
            call.driver_id = driver_id;
            call.call_transfer = DateTime.Now;
            call.call_response = DateTime.Now;
            call.call_depart = DateTime.Now;
            Ambulance amb = db.Ambulances.Find(ambulance_id);
            amb.ambulance_status = "RESERVED";
            db.Entry(amb).State = EntityState.Modified;
            db.Entry(call).State = EntityState.Modified;
            db.SaveChanges();
            /////////////////////////////////
            //Send email
            string nurse_user_id = db.Nurse_Account.Where(m => m.nurse_account_id == call.nurse_account_id).Select(m => m.nurse_account_user_id).First();
            string usr = db.AspNetUsers.Where(m => m.Id == nurse_user_id).Select(m => m.Id).First();
            string usr_mail = db.AspNetUsers.Where(m => m.Id == nurse_user_id).Select(m => m.Email).First();

            SendEmail(usr, "New call", usr_mail);

            ViewBag.Message = usr_mail;
            ////////////////////////////////
            Add_Call_history("Μεταβίβαση κλήσης", call.call_id);
            Call ca = db.Calls.Include(c => c.Ambulance).Include(c => c.Call_Status1).Include(c => c.City1).Include(c => c.Patient_Sex1).Include(c => c.Priority1).Include(c => c.Protocol).Include(c => c.Transport_Specification).Where(c => c.call_id == call.call_id).First();
            CallVM callVM = new CallVM();
            callVM.call_id = ca.call_id;
            callVM.call_status = ca.Call_Status1.name;
            callVM.ambulance_plates = ca.Ambulance.ambulance_plates;
            callVM.nurse_phone = ca.Nurse.nurse_phone;
            callVM.call_transfer = ca.call_transfer;
            callVM.call_response = ca.call_response;
            callVM.call_depart = ca.call_depart;
            callVM.nurse_fullname = ca.Nurse_Account.nurse_fullname;
            callVM.station = ca.Ambulance.Station.station_name;
            callVM.driver_name = ca.Driver.driver_name + " - " + ca.Driver.driver_phone;
            var context = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
            context.Clients.All.transfercall(callVM);
            context.Clients.All.UpdateDashBoard();
            return Json(new { result = "OK" }, JsonRequestBehavior.AllowGet);
        }

当我调用函数时,我得到以下错误:

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=mscorlib
  StackTrace:
   at System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.PostAction(Object state)
   at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)
   at System.Threading.Tasks.AwaitTaskContinuation.<>c.<ThrowAsyncIfNecessary>b__18_0(Object s)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

  This exception was originally thrown at this call stack:
    [External Code]

共1个答案

匿名用户

您看到的问题是由于请求外在代码造成的。所有请求外部代码都是危险的。

具体地说,代码调用的是,而不是之后,它将响应发送回客户端,使作为请求外部代码运行。

但是,是在ASP.NET请求上下文中调用的,因此当它试图在之后继续执行时,会遇到错误,因为该ASP.NET请求上下文已消失。响应已经发送,因此没有更多的ASP.NET请求上下文。

最好的解决方案是删除request-extrinsic代码。或者调用,或者为异步消息传递构建基本的分布式体系结构。我要说的是只使用,除非您必须提前返回,在这种情况下,您需要一个持久队列和一个工作进程。MVC操作将向队列中写入包含所有电子邮件详细信息的消息,然后返回HTTP结果。工作进程将读取该队列并发送实际的电子邮件。

任何其他解决方案都会使用request-extrinsic代码,这在本质上是危险的。具体地说,任何请求外在代码都可能在没有警告和日志的情况下停止工作。“火而忘”字面意思是“忘记”。工作(在这种情况下是电子邮件)可能会丢失。但是,如果您对此没有意见,那么您可以通过使用类似于我的AsyncEx库中的之类的东西,以不引用ASP.NET请求上下文的方式调用request-extrinsic代码。