背景
我目前正在通過終端界面重新創建具有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