mvc中使用Hangfire处理后台任务
考虑下如下代码,在数据保存后,需要发送邮件,发送邮件是个耗时的工作。
我们的目的是,数据保存成功后,就可以返回响应了,发送邮件不重要,不需要等待邮件发送成功
[HttpPost]
public ActionResult Create(Comment model)
{
if (ModelState.IsValid)
{
_db.Comments.Add(model);
_db.SaveChanges();
MailMessage message = new MailMessage();
message.To.Add("xx@126.com");
message.Subject = "主题是";
message.Body = string.Concat(HtmlEmailHeader, Body, HtmlEmailFooter);
message.BodyEncoding = System.Text.Encoding.UTF8;
message.From = new MailAddress(From);
message.SubjectEncoding = System.Text.Encoding.UTF8;
message.IsBodyHtml = true; SmtpClient client = new SmtpClient("relay.mail.server");
client.Send(Message);//耗时操作
}
return RedirectToAction("Index");
}
改成异步是否能达到这个效果呢?
答案是否定的!!虽然加入了异步方法,但是只有action里所有的代码执行完毕后才能返回响应!
await(await表达式表示等待异步方法执行完,并取返回值,因此遇到await关键字,会阻塞线程) 后面的异步方法还是要执行完毕后,才会继续执行下面的代码,跟同步方法一样,并不会节省时间。
所以异步可以提高效率/吞吐量,但是不能节省时间。
[HttpPost]
public async Task<ActionResult> Create(Comment model)
{
if (ModelState.IsValid)
{
_db.Comments.Add(model);
_db.SaveChanges();
//异步范例1
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
Console.WriteLine("上面的异步方法是否执行完跟我没关系,我还是执行到这里了");
string urlContents = await getStringTask;//必须等client.GetStringAsync执行完
Console.WriteLine(urlContents.Length.ToString());上面的语句执行完才轮到我。
//异步反例2
MailMessage message = new MailMessage();
message.To.Add("xx@126.com");
message.Subject = "主题是";
message.Body = string.Concat(HtmlEmailHeader, Body, HtmlEmailFooter);
message.BodyEncoding = System.Text.Encoding.UTF8;
message.From = new MailAddress(From);
message.SubjectEncoding = System.Text.Encoding.UTF8;
message.IsBodyHtml = true; SmtpClient client = new SmtpClient("relay.mail.server"); await client.SendMailAsync(message); //await 这里会阻塞线程,直到邮件发送完毕
}
return RedirectToAction("Index");//发送完邮件才执行到这里!
}
可以用后台线程吗?
答案也是否定的!
IIS工作线程是用于处理请求的,不适合运行后台任务,当应用程序池回收的时候,会丢掉。
最后,介绍 Hangfire
http://docs.hangfire.io/en/latest/tutorials/send-email.html#id3
mvc项目,添加nuget包 hanfire
安装包完毕后,可以看到,默认使用了sqlserver作为存储,并依赖Owin
mvc根目录创建startup.cs,并配置sqlserver连接字符串
using Hangfire;
using Microsoft.Owin;
using Owin;
using System; [assembly: OwinStartupAttribute(typeof(HangFire.Startup))]
namespace HangFire
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
string connectionStr = "Database=yourdb;Server=.;Uid=xxx;Pwd=xxx;Enlist=False;Pooling=true;Connection Reset=false;Trusted_Connection=no;Connect TimeOut=3000;";
GlobalConfiguration.Configuration
.UseSqlServerStorage(connectionStr); BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget!"));//测试 app.UseHangfireDashboard();
app.UseHangfireServer();
}
}
}
运行mvc项目,因为在startup.cs里,加了BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget!"));//测试
所以Hangfire第一次执行的时候,会在sqlserver里创建相关的表
下面把发邮件的action改造下
[HttpPost]
public ActionResult Create(Comment model)
{
if (ModelState.IsValid)
{
_db.Comments.Add(model);
_db.SaveChanges();
MailMessage message = new MailMessage();
message.To.Add("xx@126.com");
message.Subject = "主题是";
message.Body = string.Concat(HtmlEmailHeader, Body, HtmlEmailFooter);
message.BodyEncoding = System.Text.Encoding.UTF8;
message.From = new MailAddress(From);
message.SubjectEncoding = System.Text.Encoding.UTF8;
message.IsBodyHtml = true; SmtpClient client = new SmtpClient("relay.mail.server");
BackgroundJob.Enqueue(() => client.Send(message));//发送工作交给Hangfire去后台处理了
}
return RedirectToAction("Index");//不管邮件是否发送成功就返回响应了
}
mvc中使用Hangfire处理后台任务的更多相关文章
- MVC中使用Hangfire执行定时任务
需求描述 项目中有一个通知公告的功能,在后台管理员添加公告后需要推送消息给所有注册用户,让其查看消息.消息推送移动端采用极光推送,但是消息在何时发送是个问题,比如说有一个重要的会议通知,可能希望在会议 ...
- AspNet MVC中使用Hangfire执行定时任务
Hangfire在Aspnet中执行定时任务: 第一步: NuGet中加入Hangfire包 第二步: 添加Owin的自启动 第三步.Hangfire的后台控制仪表盘默认情况下只能本地访问,外网访问需 ...
- MVC中使用Hangfire按秒执行任务
更新Hangfire版本到1.7.0,才支持使用按秒循环任务执行 RecurringJob.AddOrUpdate("test",()=>writeLog("每20 ...
- 在ASP.NET Web API项目中使用Hangfire实现后台任务处理
当前项目中有这样一个需求:由前端用户的一个操作,需要触发到不同设备的消息推送.由于推送这个具体功能,我们采用了第三方的服务.而这个服务调用有时候可能会有延时,为此,我们希望将消息推送与用户前端操作实现 ...
- .NetCore MVC中的路由(2)在路由中使用约束
p { margin-bottom: 0.25cm; direction: ltr; color: #000000; line-height: 120%; orphans: 2; widows: 2 ...
- .NetCore MVC中的路由(1)路由配置基础
.NetCore MVC中的路由(1)路由配置基础 0x00 路由在MVC中起到的作用 前段时间一直忙于别的事情,终于搞定了继续学习.NetCore.这次学习的主题是MVC中的路由.路由是所有MVC框 ...
- Asp.Net MVC中使用StreamReader读取“Post body”之应用场景。
场景:有三个市场(Global.China.USA),对前台传过来的数据有些验证需要细化到每个市场去完成. 所以就出现了基类(Global)和派生类(China.USA) 定义基类(Global)Pe ...
- 6.在MVC中使用泛型仓储模式和依赖注入实现增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...
- ASP.NET Core MVC 中的 [Controller] 和 [NonController]
前言 我们知道,在 MVC 应用程序中,有一部分约定的内容.其中关于 Controller 的约定是这样的. 每个 Controller 类的名字以 Controller 结尾,并且放置在 Contr ...
随机推荐
- Django跳转
跳转问题 如果我现在停留在文章的详情页,用户未登陆,如果你要评论,或者点赞就应该回到登陆页面登陆 如果登陆成功了,就要返回到当初跳转过来的页面 第一种通过前后端传送数据 $('.hit').click ...
- 前段基础之HTML
HTML 初识 web服务本质 import socket def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s ...
- 使用wifi网卡笔记2----概念及工具iw(STA模式)
1.认证和加密的概念 (1)概念 (2)阶段划分 初级版本:认证不需要密码, 传输不需要加密 认证不需要密码, 传输需要加密(用WEP算法) 认证需要密码(用WEP算法), 传输需要加密(用WEP算法 ...
- python学习笔记(六):常用模块
一.模块.包 什么是模块? 模块实质上就是一个python文件,它是用来组织代码的,意思就是说把python代码写到里面,文件名就是模块的名称,test.py test就是模块名称. 什么是包? 包, ...
- SVN revert命令的使用
evert命令顾名思义就是对修改过的东西进行回滚操作.一般有2种情况发生时需要用到回滚的操作: 1,修改过的东西没有递交(commit) 这种情况下revert会取消之前的修改 用法:#svn rev ...
- freebsd静态路由
FreeBSD下增进静态路由的行动 1.手工添加 # route add -net 192.168.2.0/24 192.168.1.2 2. 通过rc.conf永世 设置 # Add static ...
- Android 4 学习(17):使用Content Resolver
Content Resolver简介 每个应用程序都有一个ContentResolver实例,通过getContentResolver()方法可以获取: ContentResolver cr = ge ...
- Spring3X升级到Spring4X时,出现的问题
1.1.异常描述 Description Resource Path Location Type Class 'org.springframework.http.converter.json.Mapp ...
- 【302】C# TreeView 控件使用说明
参考:C# 中treeview 树节点图标的动态加载,及选中时图标改变 参考:C# TreeView 控件的综合使用方法 参考:TreeView 类 参考:TreeNode 类 1. 添加根和子级 通 ...
- ubuntu 初始设置备忘
配置静态网络 vim /etc/network/interfaces auto eth0 #iface eth0 inet dhcp iface eth0 inet static address x. ...