异步控制器是可行的选择吗?

时间:2011-06-28 23:37:20

标签: asp.net-mvc file-io asynchronous cron

我目前有这个庞大而缓慢的代码需要永远运行....我正在重构它以使其更具可读性并且整体提供更快的体验... 基本上我在我的服务器中有一个文件夹,其中存储有大量数据的文本文件..这个脚本将从这些文件读取并通过EF向数据库添加元素...这需要很长时间才能加载。

    public class ScriptMetabolicoController : Controller
        {
            private IPortalAdministradorServices _servicioPortalAdministrador = new PortalAdministradorServices();            
IRepositorio<Historia> historiarepo = new Repositorio<Historia>();
                IRepositorio<Indicador_Metabolico> indicadorrepo = new Repositorio<Indicador_Metabolico>();

            [Authorize(Roles = "Administrador")]
            public ActionResult Index()
            {


                DirectoryInfo myDir = new DirectoryInfo(Server.MapPath("labtelFTP"));


                ViewData["sinActualizacionesPendientes"] = false;
                if (myDir.GetFiles().Count() != 0)
                {
                    try
                    {
                        foreach (FileInfo file in myDir.GetFiles())
                        {
                            if (file.Extension != ".aspx")
                            {
                                StreamReader stream;
                                stream = file.OpenText();

                                while (stream.Peek() != -1)
                                {
                                    string linea = stream.ReadLine();
                                    string cedula = linea.Substring(2, 18).Trim();
                                    Historia historia;
                                    if (historiarepo.ObtenerTodos().Where(h => h.Cedula == cedula).Count() == 1)
                                    {
                                        //Se obtiene la historia por la cédula del participante
                                        historia = historiarepo.ObtenerTodos().Where(h => h.Cedula == cedula).First();

                                        //Se inicializan las fechas de solicitud y las fechas de reporte del examen que se lee del archivo
                                        var numero = historia.Examenes_Metabolicos.Count();

                                        int anor = Convert.ToInt32(linea.Substring(216, 4));
                                        int mesr = Convert.ToInt32(linea.Substring(220, 2));
                                        int diar = Convert.ToInt32(linea.Substring(222, 2));
                                        DateTime fecha_reporte = new DateTime(anor, mesr, diar);

                                        int anos = Convert.ToInt32(linea.Substring(202, 4));
                                        int mess = Convert.ToInt32(linea.Substring(206, 2));
                                        int dias = Convert.ToInt32(linea.Substring(208, 2));
                                        DateTime fecha_solicitud = new DateTime(anos, mess, dias);

                                        //Variable que tendrá el examen en cuestión
                                        Examen_Metabolico examen;

                                        //Si es el primer indicador de un examen nuevo en la historia del participante se crea una instancia nueva
                                        if (historia.Examenes_Metabolicos.Where(e => e.Fecha_Solicitud == fecha_solicitud).Count() == 0)
                                        {

                                            examen = new Examen_Metabolico();
                                            examen.Fecha_Reporte = fecha_reporte;
                                            examen.Fecha_Solicitud = fecha_solicitud;
                                            historia.Examenes_Metabolicos.Add(examen);

                                            //Se crea en base de datos el examen vacío para luego agregarle valores metabólicos asociados a el.
                                            //historiarepo.GuardarTodo();
                                        }
                                        //Si el indicador no es el primero de un examen nuevo entonces se le asigna a la variable 'examen' la referencia del mismo
                                        else
                                        {
                                            examen = historia.Examenes_Metabolicos.Where(e => e.Fecha_Solicitud == fecha_solicitud).First();
                                        }

                                        //Se lee el código del indicador metabólico
                                        string codigo = linea.Substring(236, 6).Trim();

                                        //Si en efecto el indicador presente en la línea que se está leyendo existe se prosigue a anexarlos al examen
                                        if (indicadorrepo.ObtenerTodos().Where(i => i.Codigo == codigo).Count() != 0)
                                        {
                                            //Se carga el indicador con el que se está trabajando en una línea específica
                                            Indicador_Metabolico indicador = indicadorrepo.ObtenerTodos().Where(i => i.Codigo == codigo).First();

                                            //Se crea una nueva instancia de valor metabólico
                                            Valor_Metabolico val = new Valor_Metabolico();

                                            //Se obtienen los valores del indicador de la línea del archivo que se está leyendo
                                            string rango_alto = linea.Substring(194, 6).Trim();
                                            string rango_bajo = linea.Substring(188, 6).Trim();
                                            string unidades = linea.Substring(178, 10).Trim();
                                            bool alerta = false;
                                            string al = linea.Substring(200, 2).Trim();
                                            if (al != "")
                                                alerta = true;
                                            string valor = linea.Substring(118, 60).Trim();

                                            //Se inicializan los atributos del valor metabólico                                        
                                            //val.Examen_Metabolico_Id = examen.Id;
                                            //val.Indicador_Metabolico_Id = indicador.Id;
                                            val.Unidades = unidades;
                                            val.Rango_Alto = rango_alto;
                                            val.Rango_Bajo = rango_bajo;
                                            val.Valor = valor;
                                            val.Alerta = alerta;
                                            val.Indicador_Metabolico = indicador;
                                            examen.Valores_Metabolicos.Add(val);
                                            historiarepo.GuardarTodo();
                                        }
                                    }
                                }
                                stream.Close();
                                file.MoveTo(Path.Combine(Server.MapPath("BackuplabtelFTP"), file.Name));
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        ViewData["Error"] = true;
                        return View();
                    }
                    ViewData["Error"] = false;
                    return View();
                }
                else
                {
                    ViewData["sinActualizacionesPendientes"] = true;
                    return View();
                }
            }

        }

我知道有一个叫做异步控制器的功能,但我不确定它们是否适用于这种情况......

请给我一些关于如何做得更好的建议。

PS。我也希望定期调用这个脚本(每小时一次),但我不确定如何...

2 个答案:

答案 0 :(得分:0)

这是否需要在MVC中完成?看起来这可能是通过像Windows服务(可能是一种痛苦)或其他类型的预定应用程序,甚至可能是控​​制台应用程序。对于重复只使用文件系统或数据库执行操作的任务,我使用一个使用System.Threading.Timers的控制台应用程序。您让后台计时器线程工作,您的Web应用程序可以自由地执行以下操作:)

如果需要基于网络,这里有一个方便的帖子,介绍如何进行简单的重复任务。

http://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/

如果您想将操作转换为异步操作,那么您的控制器将如下所示:

public class ScriptMetabolicoController : AsyncController
    {
        private IPortalAdministradorServices _servicioPortalAdministrador = new PortalAdministradorServices();

           IRepositorio<Historia> historiarepo = new Repositorio<Historia>();
        IRepositorio<Indicador_Metabolico> indicadorrepo = new Repositorio<Indicador_Metabolico>();

        [Authorize(Roles = "Administrador")]
        public void IndexAsync()
        {
            AsyncManager.OutstandingOperations.Increment();

            DirectoryInfo myDir = new DirectoryInfo(Server.MapPath("labtelFTP"));

            AsyncManager.Parameters["sinActualizacionesPendientes"] = false;
            if (myDir.GetFiles().Count() != 0)
            {
                try
                {
                    foreach (FileInfo file in myDir.GetFiles())
                    {
                        if (file.Extension != ".aspx")
                        {
                            StreamReader stream;
                            stream = file.OpenText();

                            while (stream.Peek() != -1)
                            {
                                string linea = stream.ReadLine();
                                string cedula = linea.Substring(2, 18).Trim();
                                Historia historia;
                                if (historiarepo.ObtenerTodos().Where(h => h.Cedula == cedula).Count() == 1)
                                {
                                    //Se obtiene la historia por la cédula del participante
                                    historia = historiarepo.ObtenerTodos().Where(h => h.Cedula == cedula).First();

                                    //Se inicializan las fechas de solicitud y las fechas de reporte del examen que se lee del archivo
                                    var numero = historia.Examenes_Metabolicos.Count();

                                    int anor = Convert.ToInt32(linea.Substring(216, 4));
                                    int mesr = Convert.ToInt32(linea.Substring(220, 2));
                                    int diar = Convert.ToInt32(linea.Substring(222, 2));
                                    DateTime fecha_reporte = new DateTime(anor, mesr, diar);

                                    int anos = Convert.ToInt32(linea.Substring(202, 4));
                                    int mess = Convert.ToInt32(linea.Substring(206, 2));
                                    int dias = Convert.ToInt32(linea.Substring(208, 2));
                                    DateTime fecha_solicitud = new DateTime(anos, mess, dias);

                                    //Variable que tendrá el examen en cuestión
                                    Examen_Metabolico examen;

                                    //Si es el primer indicador de un examen nuevo en la historia del participante se crea una instancia nueva
                                    if (historia.Examenes_Metabolicos.Where(e => e.Fecha_Solicitud == fecha_solicitud).Count() == 0)
                                    {

                                        examen = new Examen_Metabolico();
                                        examen.Fecha_Reporte = fecha_reporte;
                                        examen.Fecha_Solicitud = fecha_solicitud;
                                        historia.Examenes_Metabolicos.Add(examen);

                                        //Se crea en base de datos el examen vacío para luego agregarle valores metabólicos asociados a el.
                                        //historiarepo.GuardarTodo();
                                    }
                                    //Si el indicador no es el primero de un examen nuevo entonces se le asigna a la variable 'examen' la referencia del mismo
                                    else
                                    {
                                        examen = historia.Examenes_Metabolicos.Where(e => e.Fecha_Solicitud == fecha_solicitud).First();
                                    }

                                    //Se lee el código del indicador metabólico
                                    string codigo = linea.Substring(236, 6).Trim();

                                    //Si en efecto el indicador presente en la línea que se está leyendo existe se prosigue a anexarlos al examen
                                    if (indicadorrepo.ObtenerTodos().Where(i => i.Codigo == codigo).Count() != 0)
                                    {
                                        //Se carga el indicador con el que se está trabajando en una línea específica
                                        Indicador_Metabolico indicador = indicadorrepo.ObtenerTodos().Where(i => i.Codigo == codigo).First();

                                        //Se crea una nueva instancia de valor metabólico
                                        Valor_Metabolico val = new Valor_Metabolico();

                                        //Se obtienen los valores del indicador de la línea del archivo que se está leyendo
                                        string rango_alto = linea.Substring(194, 6).Trim();
                                        string rango_bajo = linea.Substring(188, 6).Trim();
                                        string unidades = linea.Substring(178, 10).Trim();
                                        bool alerta = false;
                                        string al = linea.Substring(200, 2).Trim();
                                        if (al != "")
                                            alerta = true;
                                        string valor = linea.Substring(118, 60).Trim();

                                        //Se inicializan los atributos del valor metabólico                                        
                                        //val.Examen_Metabolico_Id = examen.Id;
                                        //val.Indicador_Metabolico_Id = indicador.Id;
                                        val.Unidades = unidades;
                                        val.Rango_Alto = rango_alto;
                                        val.Rango_Bajo = rango_bajo;
                                        val.Valor = valor;
                                        val.Alerta = alerta;
                                        val.Indicador_Metabolico = indicador;
                                        examen.Valores_Metabolicos.Add(val);
                                        historiarepo.GuardarTodo();
                                    }
                                }
                            }
                            stream.Close();
                            file.MoveTo(Path.Combine(Server.MapPath("BackuplabtelFTP"), file.Name));
                        }
                    }
                       AsyncManager.Parameters["Error"] = false;
                }
                catch (Exception e)
                {
                    AsyncManager.Parameters["Error"] = true; 
                }
            }
            else
            {
                AsyncManager.Parameters["sinActualizacionesPendientes"] = true;
            }


             AsyncManager.OutstandingOperations.Decrement();
        }


         public ActionResult IndexCompleted(bool error, bool sinActualizacionesPendientes )
        {
            ViewData["sinActualizacionesPendientes"] = sinActualizacionesPendientes;
            ViewData["Error"] = error;
            return View();
        }

    }

这是可以帮助你的MS文章:

http://msdn.microsoft.com/en-us/library/ee728598.aspx

希望这有帮助!

答案 1 :(得分:0)

检查一下它可能对http://quartznet.sourceforge.net/有所帮助。我打算在我当前的项目中使用它来安排一些更长时间运行的任务。