2015-11-07 123 views
0

我想从自己的AppDomain下面开始潜在的长时间运行线程,以防止Web服务器在回收期间中止它。它编译罚款,但在运行时我得到这个神秘的错误在AppDomain中创建与AppDomain相同的新AppDomain调用方法

类型未解决的成员“MyCore.MyWebService,MyCore, 版本= 5.0.0.0,文化=中立,公钥=空”。

如何找出哪些成员没有解决?

有没有更好的方法在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(); 
    }); 
    } 
} 
+1

是什么让你认为在新的AppDomain中启动一个线程会阻止IIS回收你的ASP.NET应用程序和整个w3p关联的进程?您可以简单地忘记在IIS中的后台线程上执行可靠的长时间运行任务。这不是Web服务器的设计目的。 –

+0

你是对的,我捅了一下,可能已经找到了使用Hangfire的解决方案。 – aggaton

回答

0

好吧,我终于得到它在.NET 4.0中的工作和MVC 3,必须安装Common.Logging.Core 2.2.0,因为安装的NuGet错误的版本(3.3。0)

以我初始控制器I加入下列

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))] 

在启动后台线程我添加以下代码,传入一个长期而不是类和具有工作从数据库加载POCO类。

BackgroundJob.Enqueue(() => PopulateTables(lDatabaseID, JobCancellationToken.Null)); 

入列()函数返回一个任务ID,以后可用于如果需要取消的作业,通过BackgroundJob.Delete(作业ID)的功能。

在作业方法,然后我有这个

while (idxMin < max) 
{ 
    try 
    { 
     cancellationToken.ThrowIfCancellationRequested(); 
     .... 
    } 
    catch (JobAbortedException jobEx) 
    { 
     .... 
    } 
} 

使用依赖注入是很重要的,所以我班有一个参数的构造函数补充说,重新读取连接字符串,而不是有它的通过。

public MyWebService() 
     : this(ConnectionString.GetTVConnectionString()) 
{ 
} 

public MyWebService (string sConnStr) 
{ 
    msConnStr = sConnStr; 
} 

之后,它似乎运行得很好。许多表被添加到连接字符串中指定的数据库中。到目前为止,似乎这些工作能在网络服务器上回收利用。

1

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关机,这样你就不会得到半成品孤立的工作 - 至少是只标记该任务为中止和退出干净。与迟发型已经打乱后

+0

感谢您的回答,我多花点时间,并可能在Hangfire中找到了解决方案。 – aggaton

+0

感谢您的提及。 HangFire对于我现在正在开发的项目来说看起来非常棒。我想我会在Windows服务中保留我的处理,但用HangFire替换我的半建任务系统。为什么不回答你自己的问题?我认为HangFire在这里是正确的答案。 – christutty

+0

好吧,我一整天都在努力让Hangfire玩,我似乎无法让它工作,也许我使用的库和Hangfire似乎有一些要求不匹配。它使用Owin和WebHost。如果我使用NuGet安装Hangfire,我似乎无法再启动我的Web应用程序了。我也使用.Net 4.0和MVC 3.0(目前我没有时间冒险升级,因为它似乎总是一个耗时的过程)。这就是为什么我犹豫不决的原因。但你可能比我运气好。 – aggaton