Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多线程周期性执行的C#设计模式_C#_Multithreading_Design Patterns_Thread Synchronization_Periodic Processing - Fatal编程技术网

多线程周期性执行的C#设计模式

多线程周期性执行的C#设计模式,c#,multithreading,design-patterns,thread-synchronization,periodic-processing,C#,Multithreading,Design Patterns,Thread Synchronization,Periodic Processing,我的C#Windows服务有以下要求 在服务启动时,它从数据库获取一组数据 并将其保存在内存中 具有从3个不同线程定期执行的业务逻辑 每个线程将使用步骤1中提到的数据收集中的不同数据子集执行相同的业务逻辑。每个线程将生成不同的结果集 如果数据收集发生任何更改,所有3个线程都将定期运行 当任何客户端调用服务时,服务应该能够返回线程执行的状态 我知道C#有不同的机制来实现周期性线程执行。 计时器、带睡眠的线程、事件WaitHandle等。, 我试图了解哪种线程机制或设计模式最适合此要求 最简单的解决

我的C#Windows服务有以下要求

  • 在服务启动时,它从数据库获取一组数据 并将其保存在内存中
  • 具有从3个不同线程定期执行的业务逻辑
  • 每个线程将使用步骤1中提到的数据收集中的不同数据子集执行相同的业务逻辑。每个线程将生成不同的结果集
  • 如果数据收集发生任何更改,所有3个线程都将定期运行
  • 当任何客户端调用服务时,服务应该能够返回线程执行的状态

    我知道C#有不同的机制来实现周期性线程执行。 计时器、带睡眠的线程、事件WaitHandle等。,
    我试图了解哪种线程机制或设计模式最适合此要求

    最简单的解决方案是在
    Task Method()
    样式中定义调度逻辑,并使用
    Task.Run()
    执行它们,而在主线程中,只需使用
    Task.WaitAny()等待执行完成即可。如果任务已完成,您可以再次调用
    task.WaitAny
    ,但不调用已完成的任务,而是传递
    task.Delay(timeuntinextschedule)
    。 这样,任务就不会阻塞主线程,并且可以避免仅仅为了等待而旋转CPU。通常,您可以避免在现代.NET中直接管理


    根据其他要求,如标准化错误处理、监控能力、这些计划任务的管理,您还可以依赖更强健的解决方案,如。

    更现代的方法是使用任务,但请查看原则

    namespace Test {
    
    public class Program {
    
        public static void Main() {
    
            System.Threading.Thread main = new System.Threading.Thread(() => new Processor().Startup());
            main.IsBackground = false;
            main.Start();
            System.Console.ReadKey();
        }
    }
    
    public class ProcessResult { /* add your result state */ }
    
    public class ProcessState {
    
        public ProcessResult ProcessResult1 { get; set; }
        public ProcessResult ProcessResult2 { get; set; }
        public ProcessResult ProcessResult3 { get; set; }
        public string State { get; set; }
    }
    
    public class Processor {
    
        private readonly object _Lock = new object();
        private readonly DataFetcher _DataFetcher;
        private ProcessState _ProcessState;
    
        public Processor() {
            _DataFetcher = new DataFetcher();
            _ProcessState = null;
        }
    
        public void Startup() {
            _DataFetcher.DataChanged += DataFetcher_DataChanged;
        }
    
        private void DataFetcher_DataChanged(object sender, DataEventArgs args) => StartProcessingThreads(args.Data);
    
        private void StartProcessingThreads(string data) {
    
            lock (_Lock) {
                _ProcessState = new ProcessState() { State = "Starting", ProcessResult1 = null, ProcessResult2 = null, ProcessResult3 = null };
    
                System.Threading.Thread one = new System.Threading.Thread(() => DoProcess1(data)); // manipulate the data toa subset 
                one.IsBackground = true;
                one.Start();
    
                System.Threading.Thread two = new System.Threading.Thread(() => DoProcess2(data)); // manipulate the data toa subset 
                two.IsBackground = true;
                two.Start();
    
                System.Threading.Thread three = new System.Threading.Thread(() => DoProcess3(data)); // manipulate the data toa subset 
                three.IsBackground = true;
                three.Start();
            }
        }
    
        public ProcessState GetState() => _ProcessState;
    
        private void DoProcess1(string dataSubset) {
            // do work 
            ProcessResult result = new ProcessResult(); // this object contains the result
            // on completion
            lock (_Lock) {
                _ProcessState = new ProcessState() { State = (_ProcessState.State ?? string.Empty) + ", 1 done", ProcessResult1 = result, ProcessResult2 = _ProcessState?.ProcessResult2, ProcessResult3 = _ProcessState?.ProcessResult3 };
            }
        }
    
        private void DoProcess2(string dataSubset) {
            // do work 
            ProcessResult result = new ProcessResult(); // this object contains the result
            // on completion
            lock (_Lock) {
                _ProcessState = new ProcessState() { State = (_ProcessState.State ?? string.Empty) + ", 2 done", ProcessResult1 = _ProcessState?.ProcessResult1 , ProcessResult2 = result, ProcessResult3 = _ProcessState?.ProcessResult3 };
            }
        }
    
        private void DoProcess3(string dataSubset) {
            // do work 
            ProcessResult result = new ProcessResult(); // this object contains the result
            // on completion
            lock (_Lock) {
                _ProcessState = new ProcessState() { State = (_ProcessState.State ?? string.Empty) + ", 3 done", ProcessResult1 = _ProcessState?.ProcessResult1, ProcessResult2 = _ProcessState?.ProcessResult2, ProcessResult3 = result };
            }
        }
    }
    
    public class DataEventArgs : System.EventArgs {
    
        // data here is string, but could be anything -- just think of thread safety when accessing from the 3 processors
        private readonly string _Data;
    
        public DataEventArgs(string data) {
            _Data = data;
        }
    
        public string Data => _Data;
    }
    
    public class DataFetcher {
        //  watch for data changes and fire when data has changed
        public event System.EventHandler<DataEventArgs> DataChanged;
    }
    
    名称空间测试{
    公共课程{
    公共静态void Main(){
    System.Threading.Thread main=新系统.Threading.Thread(()=>new Processor().Startup());
    main.IsBackground=false;
    main.Start();
    System.Console.ReadKey();
    }
    }
    公共类ProcessResult{/*添加结果状态*/}
    公共类ProcessState{
    public ProcessResult ProcessResult1{get;set;}
    public ProcessResult ProcessResult2{get;set;}
    public ProcessResult ProcessResult3{get;set;}
    公共字符串状态{get;set;}
    }
    公共类处理器{
    私有只读对象_Lock=新对象();
    专用只读数据获取程序\u数据获取程序;
    私有进程状态ProcessState;
    公共处理器(){
    _DataFetcher=新的DataFetcher();
    _ProcessState=null;
    }
    公共无效启动(){
    _DataFetcher.DataChanged+=DataFetcher\u DataChanged;
    }
    私有void DataFetcher_DataChanged(对象发送方,DataEventArgs args)=>StartProcessingThreads(args.Data);
    私有void StartProcessingThreads(字符串数据){
    锁{
    _ProcessState=newProcessState(){State=“Starting”,ProcessResult1=null,ProcessResult2=null,ProcessResult3=null};
    System.Threading.Thread one=新建System.Threading.Thread(()=>DoProcess1(数据));//将数据操作到一个子集
    1.IsBackground=true;
    一、启动();
    System.Threading.Thread two=新的System.Threading.Thread(()=>DoProcess2(数据));//将数据操作到一个子集
    2.IsBackground=true;
    二、启动();
    System.Threading.Thread three=新的System.Threading.Thread(()=>DoProcess3(数据));//将数据操作到一个子集
    3.IsBackground=true;
    三、开始;
    }
    }
    public ProcessState GetState()=>\u ProcessState;
    私有void DoProcess1(字符串数据子集){
    //工作
    ProcessResult=new ProcessResult();//此对象包含结果
    //完工时
    锁{
    _ProcessState=new ProcessState(){State=(_-ProcessState.State??string.Empty)+“,1完成”,ProcessResult1=result,ProcessResult2=_-ProcessState?.ProcessResult2,ProcessResult3=_-ProcessState?.ProcessResult3};
    }
    }
    私有void DoProcess2(字符串数据子集){
    //工作
    ProcessResult=new ProcessResult();//此对象包含结果
    //完工时
    锁{
    _ProcessState=new ProcessState(){State=(_-ProcessState.State??string.Empty)+“,2完成”,ProcessResult1=_-ProcessState?.ProcessResult1,ProcessResult2=result,ProcessResult3=_-ProcessState?.ProcessResult3};
    }
    }
    私有void DoProcess3(字符串数据子集){
    //工作
    ProcessResult=new ProcessResult();//此对象包含结果
    //完工时
    锁{
    _ProcessState=new ProcessState(){State=(_-ProcessState.State??string.Empty)+“,3完成”,ProcessResult1=_-ProcessState?.ProcessResult1,ProcessResult2=_-ProcessState?.ProcessResult2,ProcessResult3=result};
    }
    }
    }
    公共类DataEventArgs:System.EventArgs{
    //这里的数据是字符串,但可以是任何东西——只要考虑从3个处理器访问时的线程安全性就可以了
    私有只读字符串_数据;
    公共DataEventArgs(字符串数据){
    _数据=数据;
    }
    公共字符串数据=>\u数据;
    }
    公共类数据获取程序{
    //注意数据更改,并在数据更改时触发
    public event System.EventHandler数据已更改;
    }
    

    }

    线程仅在数据更改时运行,或者线程会定期运行检测数据是否更改并处理?@Pratekshrivastava线程会定期运行并检测数据是否更改,然后处理业务逻辑。尽管如此,我不喜欢定期检查。我将使用IsBackground=True的线程;并自己实现逻辑。在这个场景中使用Task也是类似的,只需记住将Task标记为LongRunning@PrateekShrivastava谢谢你的来信