在与中的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();
    });
  }
}

在与中的AppDomain相同的类中创建新的AppDomain调用方法

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;
}

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