背景
我目前正在通过终端界面重新创建具有GUI功能的GUI功能。所以错误不在触发事件的另一端,因为它以原始的GUI形式工作。如何使用异步事件管理线程阻塞和解除阻塞?
我在多台机器上运行由子任务组成的任务。
我订阅了事件,这些事件在进行时触发并打印出描述性消息。 要为所有Y机器的每个X子任务打印一条消息。
然后发生异步多线程操作。
我想打印出每个子任务的消息,每个子任务只解析一次。
我追踪子任务的完成情况,并保留一个2D布尔数组,其中行是机器和列子任务。
问题
调试时,我可以看到正在进入下面的事件处理方法。运行numOfSubtasksFoundEventHandler中的print语句,但在设置AutoReset事件之前,会触发多个BigTask事件,并在.WaitOne处被阻止。
但是,尽管之后运行了numOfSubtasksFound.Set(),但没有其他任何内容被打印,程序也不会执行完毕。没有任何东西能通过numOfSubtasksFound.WaitOne。
如果我在BigTaskHandler方法中取出numOfSubtasksFound.WaitOne,我会收到类似的行为,但有几条消息指出BigTask完成,然后程序停止在其他地方。
在这里管理阻止和解除封锁的最佳方法是什么?还是有一个小的修复?
目标
我需要的是,直到numOfSubtasksFoundEventHandler已经运行一次,以阻止子任务的事件处理程序方法的操作方式。我只需要numOfSubTasksFoundEventHandler只运行一次。
当前子任务事件处理程序未正确解除阻止。切换大小写代码从未在numOfSubtasksFound.Set();后执行。运行。
//MAIN
bool[] machinesDoneTasks = new bool[numOfMachines];
bool[][] machinesDoneSubtasks = new bool[numOfMachines][];
try
{
//thread/task blocking
numOfSubtasksFound = new AutoResetEvent(false);
AllSubTasksDone = new AutoResetEvent(false);
AllBigTasksDone = new AutoResetEvent(false);
//Subscribe to events to get number of subtasks and print useful information as tasks progress
numOfSubtasksFoundEvent += numOfSubtasksFoundEventHandler;
SubTaskProgEvent += SubTaskEventProgHandler; //prog stands for progress
BigTaskProgEvent += BigTaskProgEventHandler;
RunAllTasksOnAllMachines();//this will trigger the events above
//Don't exit program until those descriptive messages have been printed
numOfSubtasksFound.WaitOne();
AllSubTasksDone.WaitOne();
//SubTaskProgEvent -= SubTaskProgEventHandler;
AllBigTasksDone.WaitOne();
//BigTaskProgEvent -= BigTaskProgEventHandler;
}
catch (Exception e)
{
//print exceptions
}
//END MAIN
下面不一定是第一个要触发的事件。
internal void numOfSubtasksFoundEventHandler(object sender, EventArgs e)
{
//get number of subtasks from args after checking for nulls, empty arrays
for (int i = 0; i < numOfSubtasks; i++)
machinesDoneSubtasks[i] = new bool[numOfSubtasks];
Console.WriteLine("number of subtasks found");
numOfSubtasksFoundEvent -= numOfSubtasksFoundEventHandler;//don't subscribe to event where we get this from anymore
if (numOfSubtasksFound != null)
numOfSubtasksFound.Set(); //stop blocking
}
子任务事件不一定在大任务事件之前得到处理。
internal void SubtaskEventProgHandler(object sender, EventArgs e)
{
//null, empty checks on args
//Wait until we know how many subtasks there are and the 2D boolean array is fully built
numOfSubtasksFound.WaitOne();
switch (e.WhatHappened)
{
Case.TaskComplete:
Console.Write(e.Machine + " is done subtask " + e.subTask);
//logic to determine machine and subtask
machinesDoneSubtasks[machine][Subtask] = true;
if (AllSubTasksDone != null && machinesDoneSubtasks.OfType<bool>().All(x => x))
AllSubTasksDone.Set(); //stop blocking when 2D array is all true
break;
//other cases, different prints, but same idea
}
}
BigTask进度事件发生在处理的开始中间和结束。我只打印出我想要的案例的细节。
internal void BigTaskProgEventHandler(object sender, EventArgs e)
{
//Wait until we know how many subtasks there are and the 2D boolean array is fully built before printing
numOfSubtasksFound.WaitOne();
//null, empty exception checks
switch (e.WhatHappened)
{
Case.TaskComplete:
Console.Write(e.Machine + " is done task " + e.subTask);
//logic to determine machine
machinesDoneTasks[machine] = true;
if (AllBigTasksDone != null && machinesDoneTasks.All(x => x))
AllBigTasksDone.Set();
break;
}
//other cases, different prints, but same idea
}
在.Net中管理异步操作的最佳方式是使用async/await。什么是你的要求?你想解决什么问题? – radianz
你可以发布'RunAllTasksOnAllMachines'的代码吗?另外,你能缩短你的问题吗?我们不需要像“Asynchronous multithreading shenaniegans thenue”这样的行。我还没有弄清楚“通过非gui界面”。和“触发事件的另一端”。手段。你需要重新阅读你写的内容,并确保它是可以理解的。 – Enigmativity
@RobertoBastianic更新了描述,希望它更清晰。就像它在上面,我没有列出的所有东西都能正常工作。 我会更新我的问题,尝试使其更清晰。 – despair