2017-06-20 72 views
0

我正在编写一个调度程序作为练习的请求,所以我不能使用Windows的调度程序。EventHandler在C中始终为空#

我的调度程序的结构几乎完整,它们仅缺少一些辅助细节。

作为一个请求,我需要使用一个主线程来控制在执行时是否有任务被编程,如果是的话,我必须启动一个辅助线程来执行这个过程。其中一个请求是使用有限数量的线程,因此我有一个变量来计算执行中的实际线程数。我想在辅助线程结束时使用事件向主线程发信号。我搜索了很多,在这里和其他许多网站。几乎每个网站都提出了我已经实施的解决方案,但在我的情况下,我使用的EventHandler始终为空......并且我不明白为什么。有人能帮助我吗?非常感谢 !!

这是代码。

这是类二级螺纹:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Diagnostics; 

namespace scheduler 
{ 


    public delegate void EventHandler(object sender, EventArgs e); 

    public class Thread_work 
    { 

     public event EventHandler ExecutionFinished; 

     Job job; 

     public Thread_work(Job j) 
     { 
      job = j; 
      LaunchCommandLineApp(); 
     } 

     public void LaunchCommandLineApp() 
     { 
      // Use ProcessStartInfo class 
      ProcessStartInfo startInfo = new ProcessStartInfo(); 
      startInfo.CreateNoWindow = false; 
      startInfo.UseShellExecute = false; 
      startInfo.FileName = job.process; 
      startInfo.WindowStyle = ProcessWindowStyle.Hidden; 
      var count = job.args.Count(c => c == ';'); 
      startInfo.Arguments = "-f "; 
      while (count > 1) 
      { 
       startInfo.Arguments += job.args.Substring(0, job.args.IndexOf(';', 0)); 
       job.args = job.args.Substring(job.args.IndexOf(';', 0) + 1, job.args.Length - 1); 
       count--; 
      } 
      if (count == 1) startInfo.Arguments += job.args.Substring(0, job.args.IndexOf(';', 0)); 

      try 
      { 
       // Start the process with the info we specified. 
       // Call WaitForExit and then the using statement will close. 
       using (Process exeProcess = Process.Start(startInfo)) 
       { 
        exeProcess.WaitForExit(); 
        InvokeExecutionFinished(new EventArgs()); 
       } 
      } 
      catch 
      { 
       // Log error. 
      } 



     } 

     protected virtual void InvokeExecutionFinished(EventArgs e) 
     { 
      if (ExecutionFinished != null) 
       ExecutionFinished(this, e); 
     } 

    } 
} 

这是类调度的:

using System; 
using System.Collections.Generic; 
using System.Collections.Concurrent; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Diagnostics; 
using System.Linq; 
using System.Text; 

using System.Runtime.InteropServices; 


namespace scheduler 
{ 

    /// <summary>Custom TaskScheduler that processes work items in batches, where 
    /// each batch is processed by a ThreadPool thread, in parallel.</summary> 
    /// <remarks> 
    /// This is used as the default scheduler in several places in this solution, by, 
    /// for example, calling it directly in <see cref="TaskExtensions.ForEachAsync"/>, 
    /// or by accessing the relevant property of the static <see cref="TaskSchedulers"/> 
    /// class.</remarks> 
    public class ParallelTaskScheduler 
    { 

     public event EventHandler ExecutionFinished; 

     public bool stop_scheduler = false; 

     public int maxDegreeOfParallelism, active_thread; 

     public LinkedList<Job> jobs = new LinkedList<Job>(); 

     public ParallelTaskScheduler(int maxDegreeOfParallelism) 
     { 
      if (maxDegreeOfParallelism < 1) 
       throw new ArgumentOutOfRangeException("maxDegreeOfParallelism"); 

      this.maxDegreeOfParallelism = maxDegreeOfParallelism; 
     } 

     public ParallelTaskScheduler() : this(Environment.ProcessorCount) { } 


     public void QueueJob(Job task) 
     { 

      lock (jobs) jobs.AddLast(task); 

     } 

     private void MainThread() { 

      DateTime start, stop, now; 
      now = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, 00); 

      while (!stop_scheduler) 
      { 
       start = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 00); 
       now = now.AddMinutes(1); 
       stop = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 00); 

       foreach (Job j in jobs) 
       { 

        if (!j.mutex && j.date <= stop && j.date >= start) 
        { 
         if (active_thread < maxDegreeOfParallelism) 
         { 
          //Avvia thread esecuzione 
          j.mutex = true; 
          Thread_work th = new Thread_work(j); 
          th.ExecutionFinished += new EventHandler(this.th_executionFinished); 
          active_thread++; 
          //Al termine controlla se ricorrente 
         } 

        } 
       } 



       Thread.Sleep(20000); 
      } 

     } 

     private void th_executionFinished(object sender, EventArgs e) { 
      active_thread--;    
     } 

     void Connect() { 

     } 

     /// <summary>Runs the work on the ThreadPool.</summary> 
     /// <remarks> 
     /// This TaskScheduler is similar to the <see cref="LimitedConcurrencyLevelTaskScheduler"/> 
     /// sample implementation, until it reaches this method. At this point, rather than pulling 
     /// one Task at a time from the list, up to maxDegreeOfParallelism Tasks are pulled, and run 
     /// on a single ThreadPool thread in parallel.</remarks> 
     public void RunTasks() 
     { 
      active_thread = 0; 
      stop_scheduler = false; 
      Task.Factory.StartNew(MainThread); 
     } 


     public void StopTasks() 
     { 

      stop_scheduler = true; 

     } 
    } 

/* [StructLayout(LayoutKind.Explicit)] 
    public class OverlapEvents 
    { 
     [FieldOffset(0)] 
     public Thread_work Source; 

     [FieldOffset(0)] 
     public ParallelTaskScheduler Target; 
    }*/ 
} 

的问题是在类Thread_word ExecutionFinished的事件,那就是永远空值。根据我所做的研究,我的代码似乎是正确的,但显然不是。我没有更多的想法可以解决问题,所以我希望有人能帮助我!谢谢!

回答

2

您从构造函数中调用LaunchCommandLineApp; EventHandler为空,因为您在new Thread_work(j)之后的下一行中设置它,这已经太晚了,因为构造函数已经执行。

首先,不要在构造函数中调用:

public Thread_work(Job j) 
{ 
    job = j; 
} 

然后调用LaunchCommandLineApp你设置委托后:

Thread_work th = new Thread_work(j); 
th.ExecutionFinished += new EventHandler(this.th_executionFinished); 
th.LaunchCommandLineApp();