【问题标题】:WCF: Method return a response, after spawning a thread to do background processingWCF:方法返回一个响应,在产生一个线程做后台处理之后
【发布时间】:2020-07-12 09:27:31
【问题描述】:

所以我有以下情况。我的 WCF 中有一个方法,客户端将在其中发送请求,然后 WCF 服务将执行一些后台处理并调用外部 Web 服务方法,该方法将立即响应确认(在后台处理完成之前)。

我想到的方法是让我的 WCF 方法在生成一个线程进行后台处理后返回一个响应,并调用外部 web 服务。流程是这样的:

  • 调用者向 INITIAL_CALL 发送请求

  • WCF 启动一个调用 PROCESS 的线程

  • WCF 返回真

  • PROCESS 调用 EXTERNALWS 并在 postResponse 中获得响应

  • postReponse 被记录到数据库中

参见下面的示例代码:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class Service : IService


public bool INITIAL_CALL()
{

     new Thread(()=>
                {
                    PROCESS();
                }).Start();
    return true;
}


private void PROCESS()
{
    //Do some background processing and create request for call below
    var processRequest = "Request goes here";
    using (var client = new EXTERNALWS.ResponseTypeClient())
    {
       var postResponse = client.POST(processRequest);

       //Log postResponse to database

    }

}

考虑到 PROCESS() 可能会运行很长时间,我只是想看看是否有更好的方法使用 WCF 和 IIS 来执行此操作?或者,如果有任何我必须考虑的陷阱,即 IIS 应用程序池回收破坏线程。

【问题讨论】:

  • WCF 调用无法按您希望的方式工作。已经有大量关于您是否应该或如何在 WCF 中运行长时间运行的任务的帖子,stackoverflow.com/questions/11087826/… 但是,请记住,WCF 不是为此而设计的,SignalR 将是一个更好的选择。
  • 我在这里看到了这个例子:social.msdn.microsoft.com/Forums/vstudio/en-US/… 这似乎描述了我想要实现的目标。我只是想知道是否有任何需要考虑的事项?您分享的帖子很笼统且含糊不清,似乎需要创建一个单独的应用程序来运行长时间运行的任务。另外,如何在上述流程中使用 SignalR?
  • 我唯一要补充的是,您所说的线程没有描述您要实现的目标。

标签: wcf asynchronous iis application-pool


【解决方案1】:

我已经找到了解决方案。我最终使用 Hangfire 进行所需的后台处理 (https://www.hangfire.io/)。 Hangfire 似乎是专门为此而设计的。我已经按照他们主页上的文档在一个单独的 ASP MVC 应用程序中实现了它。我还将它配置为始终在 IIS 上运行。设置 Hangfire 的所有说明和示例代码都可以在这里找到https://docs.hangfire.io/en/latest/index.html。我必须更改流程(因为我没有像以前那样手动生成任何新线程),并且还在数据库中创建一个新表,以便 WCF 应用程序中的 INITIAL_CALL 将所有长时间运行的作业排队(稍后将被拾取)并由 Hangfire 执行)。请记住,这与 Hangfire 的队列是分开的,Hangfire 将在预定义的时间间隔内检查此表,并将检查存储了要调用的函数、其参数以及作业是否已被拾取的指示符的数据库表是否挂火(以避免此处描述的重入场景https://docs.hangfire.io/en/latest/best-practices.html)。一点额外的工作,但就像一个魅力。

流程现在的工作方式如下:

  • 调用者向 INITIAL_CALL 发送请求

  • 在 INITIAL_CALL 中,在一个新的数据库表中创建一个条目(这是作业 Hangfire 将在预定义的时间间隔内检查的队列)。

  • INITIAL_CALL 返回真

  • Hangfire 使用 PROCESS_JOBS 以预定义的时间间隔检查这个数据库表(这个时间间隔可以在 Hangfire 本身中定义)。

  • 如果有一个排队的项目,PROCESS_JOBS 继续并调用 EXTERNALWS 并在 postResponse 中获得响应。如果没有,它就退出并且什么也不做。

  • postReponse 被记录到数据库中。

查看下面更新的示例代码:

WCF 应用程序

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class Service : IService


public bool INITIAL_CALL()
{
   //Add job queue entry in database table to be picked up by Hangfire 
    return true;
}

Hangfire 应用程序

public void PROCESS_JOBS()
{
    //Check in a predefined interval if there is a pending job in the queue. 
    //If there is continue with below, otherwise exit function.

    //Do some background processing and create request for call below
    var processRequest = "Request goes here";
    using (var client = new EXTERNALWS.ResponseTypeClient())
    {
       var postResponse = client.POST(processRequest);

       //Log postResponse to database

    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-19
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 2015-01-19
    相关资源
    最近更新 更多