转换C#控制台>;服务类调用自身时如何保留字典?

转换C#控制台>;服务类调用自身时如何保留字典?,c#,.net,service,C#,.net,Service,我正在尝试转换一个简单的控制台应用程序,以便它可以使用嵌套的service类(下面的相关代码)作为服务使用。其目的是创建一个服务,在Run方法中或多或少地以设定的间隔(最终,~每小时)执行操作 简而言之,服务的OnStart调用我自己的Start方法一次,这会创建一个计时器。在计时器内部,我正在创建程序类的一个实例,并执行运行方法,直到它完成。我相信这是一个有效的实现我想要的,不会留下资源悬而未决 Run方法所做的部分工作是为它无法在文件系统上执行的操作建立一个字典,我希望在以后调用Run时保留

我正在尝试转换一个简单的控制台应用程序,以便它可以使用嵌套的
service
类(下面的相关代码)作为服务使用。其目的是创建一个服务,在
Run
方法中或多或少地以设定的间隔(最终,~每小时)执行操作

简而言之,服务的
OnStart
调用我自己的
Start
方法一次,这会创建一个计时器。在计时器内部,我正在创建
程序
类的一个实例,并执行
运行
方法,直到它完成。我相信这是一个有效的实现我想要的,不会留下资源悬而未决

Run
方法所做的部分工作是为它无法在文件系统上执行的操作建立一个字典,我希望在以后调用
Run
时保留该字典,以便在可能的情况下再次尝试这些操作。实现这一点的最佳实现是什么?我有点生疏,也不太相信我做的事情是正确的,但我正试图尽快跟上进度,所以任何帮助都是非常感谢的

partial class Program{
    static object timerLck = new object();

    public class Service : ServiceBase{
        public Service(){
            ServiceName = Program.ServiceName;
        }
        protected override void OnStart(string[] args){
            Program.Start(args);
        }
        protected override void OnStop(){
            Program.Stop();
        }
    }

    static void Main(string[] args){
        if (!Environment.UserInteractive)
            using (var service = new Service())
                ServiceBase.Run(service);
        else{
            Start(args);
            Stop();
        }
    }

    private static void Start(string[] args){
        Timer t = new Timer(CallTimer, null, 0, 50000);
        Console.ReadKey();
    }

    private static void Stop(){
        //???
    }

    static void CallTimer(object state){
        bool Lock = false;
        try{
            Lock = Monitor.TryEnter(timerLck);
            if (Lock){
                Program Prg = new Program()
                var task = Task.Run((Func<Task<int>>)Prg.Run);
                task.Wait();
            }
        }
        finally{
            if (Lock) Monitor.Exit(timerLck);
        }
    }

    //Perform the repeated actions here 
    private async Task<int> Run()
    {
        Dictionary<string, Metadata> d = new Dictionary<string, Metadata>();
        //...            
        return 0;
    }
}
部分类程序{
静态对象timerLck=新对象();
公共类服务:ServiceBase{
公共服务(){
ServiceName=Program.ServiceName;
}
启动时受保护的覆盖无效(字符串[]args){
程序启动(args);
}
受保护的覆盖void OnStop(){
Program.Stop();
}
}
静态void Main(字符串[]参数){
如果(!Environment.UserInteractive)
使用(var service=new service())
ServiceBase.Run(服务);
否则{
启动(args);
停止();
}
}
私有静态无效开始(字符串[]args){
计时器t=新计时器(CallTimer,null,0,50000);
Console.ReadKey();
}
私有静态无效停止(){
//???
}
静态void CallTimer(对象状态){
布尔锁=假;
试一试{
锁定=监视器.TryEnter(timerLck);
如果(锁定){
程序Prg=新程序()
var task=task.Run((Func)Prg.Run);
task.Wait();
}
}
最后{
如果(锁定)监视器退出(timerLck);
}
}
//在此处执行重复的操作
专用异步任务运行()
{
字典d=新字典();
//...            
返回0;
}
}

您只需运行accept a Dictionary作为参数并返回填充的Dictionary即可

private async Task<Dictionary<string, Metadata>> Run(Dictionary<string, 
    Metadata> previousErrors)
{
    Dictionary<string, Metadata> d = new Dictionary<string, Metadata>();
    //...            
    return d;
}
static void CallTimer(object state){
        bool Lock = false;
        try{
            Lock = Monitor.TryEnter(timerLck);
            if (Lock){
                Program Prg = new Program()
                var task = Task.Run(()=>Run(PreviousErrors));
                PreviousErrors = task.Result;
            }
        }
    finally{
        if (Lock) Monitor.Exit(timerLck);
    }
}

请注意,我只是针对您的问题,而不是代码其余部分的质量。这可能与您的问题范围之外的改进有关。

如果您需要按计划(例如每小时)运行某些代码,请使用Windows任务计划程序。这就是它的设计目的。通过这样做,你可能会保持你的应用程序作为一个控制台应用程序,几乎没有变化。至于跟踪需要重试的操作,您可能必须将其存储在某种类型的文件中。事实上,Microsoft自己已经将一些常规操作从服务中移出,并转移到任务调度程序中。诸如chkdsk、碎片整理、Windows Update等功能。@Christopher她正在做一项Windows服务,它的功能比计划任务更多。例如,可以将它们配置为故障时重新启动和启动时运行等@YuliBonner:task Scheduler具有所有这些选项。然后是一吨。它也不需要完全重写控制台应用程序。您可能正在考虑一种较旧的任务调度程序模型。“当前的任务非常强大。@Christopher很公平,一个计划任务可能也可以。如果她也决定走这条路,我的解决方案应该会奏效。尤里,我感谢你的反馈!现在您将其放入文本中,显然只需在
Run
中返回字典即可。我修改了
var task=task.Run(()=>Prg.Run(PreviousErrors))
避免引用非静态方法
Run
error,到目前为止看起来还不错。关于你的质量记录,如果你有机会,你能简单地评论一下你建议我重访的内容吗?我感谢有机会提高我的理解力@Alice用于一般代码检查。另外,如果这个答案对你有效,请选择它作为答案,这样我会获得一些声誉。谢谢尤里,我感谢你的帮助,并按照你的建议去做;我没有意识到代码审查网站的存在。我已经在下面的链接上发布了我的问题,如果你觉得可以对你表示我应该重温的文章发表评论,但是如果你很忙,请不要感到有任何压力:再次感谢你的帮助!