繁体   English   中英

C#中的EventHandler始终为null

[英]EventHandler is always null in C#

我正在编写一个调度程序作为一项练习的请求,所以我不能使用Windows的调度程序。

我的调度程序的结构几乎是完整的,只缺少一些次要细节。

作为请求,我需要使用主线程来控制执行时是否编写了任务,如果是,则必须启动辅助线程来执行该过程。 请求之一是使用有限数量的线程,因此我有一个变量,用于计算执行中的实际线程数。 我想使用一个事件在辅助线程完成时向主线程发出信号。 我在这里和许多其他网站上进行了大量搜索。 实际上,每个站点都提供了我已实现的解决方案,但就我而言,我使用的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事件上,该事件始终为null。 根据我所做的研究,看来我的代码是正确的,但显然不是。 我对问题可能出在哪里没有更多的想法,所以我希望有人可以帮助我! 谢谢!

您正在从构造函数中调用LaunchCommandLineApp EventHandler为null,因为您将其设置在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();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM