簡體   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