我正在编写一个调度程序作为练习的请求,所以我不能使用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。根据我所做的研究,似乎我的代码是正确的,但显然不是。我对问题可能在哪里没有更多的想法,所以我希望有人可以帮助我!谢谢!
答案 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();