在与中的AppDomain相同的类中创建新的AppDomain调用方法
本文关键字:AppDomain 调用 创建 方法 | 更新日期: 2023-09-27 18:21:13
我想在它自己的AppDomain中从可能长时间运行的线程下面开始,以防止Web服务器在回收过程中中止它。它编译得很好,但在运行时我收到了这个神秘的错误
未解析成员"MyCore.MyWebService,MyCore,"的类型,Version=5.0.0.0,Culture=neutral,PublicKeyToken=null'。
如何查找未解决的成员?
有没有更好的方法在MVC业务服务层中运行一个长期存在的线程,而不会被服务器回收机制中止?
这是代码:
namespace MyCore
{
[Serializable]
public class MyWebService : IMyWebService
{
AppDomain domain = AppDomain.CreateDomain("Domain");
Thread.CurrentThread.Name = "MVCThread";
domain.SetData("lDatabaseID", lDatabaseID);
domain.DoCallBack(() =>
{
long lID = Convert.ToInt64(AppDomain.CurrentDomain.GetData("lDatabaseID"));
Thread thread = new Thread(
(() =>
{
PopulateTables(lID );
}));
thread.Name = "DomThread";
thread.Start();
});
}
}
IIS经过了大量优化,可以非常快速地响应数百个小型同时请求,但它不是您尝试的正确工具。你可以尝试解决这个问题,但从长远来看,你最好构建一个专为长期任务设计的工具。下次出现此问题时,您将获得一个预打包的解决方案。
其基本思想是创建一个外部应用程序,通过某种方式将任务传递给它并返回结果来进行后台处理。我喜欢使用数据库进行通信,因为大多数需要baground处理的web应用程序都已经使用了数据库。添加一个包含{status、startedDateTime、finishedDateTime和parameters等}的"tasks"表,然后编写一个外部应用程序,该应用程序将定期查找新任务,完成任务并更新数据库。你的网站可以轮询数据库的状态,或者你的应用程序可以调用AJAX来通知网站作业何时完成(如果有人正在等待作业完成,那么在网站标题中显示等待/完成任务的小iframe会很有用,而且很容易完成)。
编辑:在你做上述审查HangFire(它在IIS中工作,作为Windows服务或控制台应用程序)之前。相同的原则,但是预包装的解决方案。请注意,我还没有实现这一点,但它看起来不错。
尽管设置起来有点麻烦,但如果您可能有多个任务并且需要快速响应,则将此任务交给Windows服务是一个不错的方法。网上有很多教程可以帮助您创建Windows服务,例如http://www.codeproject.com/Articles/106742/Creating-a-simple-Windows-Service但你必须在此基础上构建一个简单的任务执行器,所以如果你想这样做,我会寻找一个预先构建的任务引擎(我找不到,但我可能用错了搜索短语)。
但是,如果周转时间不重要,那就太过分了,对你来说,更好的方法可能是创建一个小型控制台应用程序,由任务调度程序每五分钟启动一次。它将连接到数据库,执行任何等待的任务,然后再次关闭。这比Windows服务更容易调试和安装,并实现了将任务执行从IIS中移出的相同目标。
请记住,您仍然必须检测和处理Windows关闭,这样您就不会得到完成一半的孤立作业——至少只需将该任务标记为已中止并干净退出即可。
好吧,在处理了Hangfire之后,我终于可以在.Net 4.0和MVC 3中工作了。不得不安装Common.Loggin.Core 2.2.0,因为NuGet安装了错误的版本(3.3.0)
在我的初始控制器中,我添加了以下
namespace Core.Controllers
{
...
public void Configuration(IAppBuilder app)
{
app.UseHangfire(config =>
{
config.UseSqlServerStorage(ConnectionString.GetTVConnectionString());
config.UseServer();
});
}
...
}
ConnectionString.GetTVConnectionString()从配置文件中获取连接字符串。
在顶部,我添加了以下
[assembly: OwinStartup(typeof(Core.Controllers.BaseController))]
在启动后台线程的代码中,我添加了以下内容,传入了一个long而不是类,并让作业从数据库加载POCO类。
BackgroundJob.Enqueue(() => PopulateTables(lDatabaseID, JobCancellationToken.Null));
Enqueue()函数返回一个作业id,稍后可以通过BackgroundJob.Delete(jobid)函数在需要时使用该id来取消作业。
在工作方法中,我有这个
while (idxMin < max)
{
try
{
cancellationToken.ThrowIfCancellationRequested();
....
}
catch (JobAbortedException jobEx)
{
....
}
}
使用依赖项注入很重要,所以我的类添加了一个无参数构造函数,它可以重新读取连接字符串,而不是将其传入
public MyWebService ()
: this(ConnectionString.GetTVConnectionString())
{
}
public MyWebService (string sConnStr)
{
msConnStr = sConnStr;
}
在那之后,它似乎运行得很好。将向连接字符串中指定的数据库中添加多个表。到目前为止,这些工作似乎可以在网络服务器上回收。