在后台线程上调用任务并使用Parallel.Foreach时出现问题 [英] Issue with invoking tasks on a background thread and using Parallel.Foreach

查看:70
本文介绍了在后台线程上调用任务并使用Parallel.Foreach时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好

你好

我正在遵循C#Windows服务,该服务实例化MyProductsManager类,如下所示:

  public static void Main(string [] args)
        {
            ServiceBase [] ServicesToRun;
            ServicesToRun =新的ServiceBase [] 

新的MyWindowsServiceHost() 
};
            ServiceBase.Run(ServicesToRun);
        }

 公共类MyWindowsServiceHost:ServiceBase
    {
公共ServiceHost m_serviceHost = null;
       公共MyWindowsServiceHost()
        {

        }

       受保护的重写void OnStart(string [] args)
        {
           试试
            {
               如果(m_serviceHost!= null)
                    m_serviceHost.Close();
                m_serviceHost =新的ServiceHost(typeof(MyProductsManager));
                m_serviceHost.Open();

            }
}

公共类MyProductsManager
{

MyProductsManager()
{
    SendStartServiceEmailAlert(); ---用于通知用户服务已启动
    GetProductsInfo();
}
....
....
....
}
需要在后台线程上调用GetProductsInfo(),以便Windows Service(从Service Control Manager中)立即启动,而不是等待GetProductsInfo()方法完成.

GetProductsInfo()需要执行三个操作:
步骤#1.调用GetProductList()获取所有产品的列表
步骤#2.通过调用GetProductDetails()并行获取400个产品中每个产品的数据(可能使用Parallel.ForEach ??).
3.SendTaskCompletionEmailAlert()-此警报用于通知用户说已提取所有400种产品的详细信息".仅在步骤1和2完成后才需要调用此方法.
请问我该如何实现?


谢谢

I've following C# windows service that instantiates MyProductsManager class as follows:

 public static void Main(string[] args)
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 

new MyWindowsServiceHost() 
};
            ServiceBase.Run(ServicesToRun);
        }

 public class MyWindowsServiceHost: ServiceBase
    {
public ServiceHost m_serviceHost = null;
        public MyWindowsServiceHost()
        {

        }

        protected override void OnStart(string[] args)
        {
            try
            {
                if (m_serviceHost != null)
                    m_serviceHost.Close();
                m_serviceHost = new ServiceHost(typeof(MyProductsManager));
                m_serviceHost.Open();

            }
}

public class MyProductsManager
{

MyProductsManager()
{
    SendStartServiceEmailAlert();---for informing users that service has started
    GetProductsInfo();
}
....
....
....
}
GetProductsInfo() needs to be invoked on a background thread so that the windows service(from within Service control Manager) starts up immediately instead of waiting for GetProductsInfo() method to complete.

GetProductsInfo() needs to carry out three operations:
Step # 1.Call GetProductList() to get a list of all products
Step # 2.Get data for each of the 400 products in parallel(may be using Parallel.ForEach??) by calling GetProductDetails().
3.SendTaskCompletionEmailAlert() --This alert is for informing users saying "details for all 400 products have been fetched".This method needs to be invoked only after step #1 and #2 have been completed. 

How do I achieve this please?


Thanks.

-

推荐答案

此代码均不属于您的服务的构造函数. Windows服务可以构建,但无法启动.服务的所有工作应在OnStart方法中完成.您的所有工作都必须在辅助工作线程上完成,因此无需执行任务 正确的解决方案.您应该在OnStart方法中创建一个常规工作线程,然后让它完成所有工作.

None of this code belongs in the constructor for your service. A windows service can be constructed but never started. All work for a service should be done in the OnStart method. All your work has to be done on a secondary worker thread so tasks aren't the correct solution here. You should create a regular worker thread in your OnStart method and then have it do all the work.

对于您的呼叫顺序,我不确定为什么您将Windows服务用作永久运行的服务.因此,您的工作线程在通知用户之后会做什么?根据您的描述,您给出的所有代码(将在工作程序中 线程)可以按顺序运行.没有理由产生任何其他任务(也许不是并行获取).所以我可以设想一下:

As for the ordering of your calls I'm not sure why you're using a windows service as a service runs forever. So your worker thread will be doing what after it has notified the users? Based upon your description all the code you gave (which will be in a worker thread) can be run sequentially. There is no reason to spawn any additional tasks (other than perhaps the parallel fetching). So I could envision this:

public class MyWindowsService : ServiceBase
{
   protected override void OnStart ( string[] args )
   {
      //Start worker thread
      _thread = new Thread(DoWork);
      _thread.IsBackground = true;
      _thread.Start();
   }

   protected override void OnStop ()
   {
      _terminate.Set();

      //Wait for worker to terminate
      //SCM will kill it if it takes too long
      _thread.Wait();
   }

   private void DoWork ( )
   {
      //Get data (could use Task here with cancellation token so you can terminate when service terminates)
      var data = ...;

      //Start parallel work
      ...

      //Block until work complete or termination request
      SendEmail();
   
      //Now what, your thread should not terminate???
   }

   private Thread _thread;
   private ManualResetEvent _terminate = new ManualResetEvent(false);
}

该事件是这样的,因此OnStop方法可以告诉工作线程终止.该线程不应在此之前终止,否则您的服务将基本失效.如果您不需要循环运行此代码或其他任何操作,则可能不应该使用 根本没有服务.

The event is so the OnStop method can tell the worker thread to terminate. The thread should not terminate before that otherwise your service is basically dead. If you don't need to run this code in a loop or anything then you probably shouldn't be using a service at all.

迈克尔·泰勒
http://www.michaeltaylorp3.net

Michael Taylor
http://www.michaeltaylorp3.net


这篇关于在后台线程上调用任务并使用Parallel.Foreach时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆