在C#

时间:2017-06-20 21:02:56

标签: c# eventhandler

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

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

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

1 个答案:

答案 0 :(得分:3)

您正在从构造函数中调用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();