2017-06-20 13 views
0

私は演習のリクエストとしてスケジューラを書いていますので、私はそのウィンドウを使用できません。EventHandlerはC#で常にnullです。

私のスケジューラの構造はほぼ完成していますが、二次的な詳細はほんのわずかです。

リクエストとして、実行時にプログラムされたタスクがあるかどうかを制御するためにメインスレッドを使用する必要があります。そうであれば、そのプロセスを実行するためにセカンダリスレッドを開始する必要があります。要求の1つは限られた数のスレッドを使用することです。そのため、実行中のスレッドの実際の数を数える変数があります。私は、セカンダリスレッドが終了したときにメインスレッドに信号を送るためにイベントを使いたい。私はたくさんの、ここや他の多くのサイトで検索しました。実際にはすべてのサイトが私が実装したソリューションを提案していますが、私のケースでは、私が使ったEventHandlerは常にnullです...なぜか分かりません。誰か助けてくれますか?どうもありがとう !!

ここにコードがあります。

これは、セカンダリスレッドのクラスである:

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をコンストラクタから呼び出しています。 EventHandlernew 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(); 
関連する問題