Управляющий компьютер создает задачу/поток, который обрабатывает каждое задание, назначенное ему. arduino асинхронно (приведение механизма в исходное положение, установка положения, перемещение и т. д.) arduino сообщает, как он выполняет каждое задание ("успешно размещено", "перемещено в положение" и т. д.), что позволяет продолжить выполнение задания его путь к коду.
Однако все, что я пробовал, имеет некоторые проблемы, поэтому мне нужен совет, как действовать.
Вот что я пробовал. (Не стесняйтесь спрашивать об этом подробнее.)
- зацикливается, когда я использовал систему на основе потоков вместо системы, основанной на задачах. Это съедало весь процессор, когда у меня было несколько потоков, ожидающих ответа от Arduino (например, я пытался переместить MoveAxis1 и moveAxis4 одновременно, и оба ждали разрешения на продолжение, что приводило к сбою программы из-за перегрузки). использование памяти.)
Код: Выделить всё
while(!doneWaiting){thread.sleep(5);}
- Неоднократный анализ входных данных SerialPort на наличие строки, означающей продолжение этого задания. Также съедал память и иногда игнорировал ответ «ОК, чтобы продолжить задание».
- В конце концов я реализовал SerialPort.DataReceived событие и использовал ManualResetEvents.WaitOne(). Когда новые данные были найдены в SerialPort, он вызывал метод ManualResetEvents.Set() и позволял коду проходить мимо WaitOne(). Это был бы лучший вариант, но он запускает ВСЕ ожидающие потоки, а не один конкретный ожидающий поток за раз. Мне нужно, чтобы некоторые потоки ждали их личного ответа, в то время как другим разрешено продолжить.
Код: Выделить всё
class Program
{
public static SerialPort serialPort = new SerialPort("COM9", 9600, Parity.None, 8, StopBits.One);
public static string newDataContent = string.Empty;
public static bool homed = false;
static TaskCompletionSource homeRelease = new TaskCompletionSource(); //this is the important bit
static void Main(string args[])
{
serialPort.DtrEnable = true;
serialPort.DataReceived += new SerialPortDataReceivedEventHandler(serialPort_ReadArduinoData);
serialPort.Open();
//...
char cmdType = Console.ReadLine().ToLower().ToCharArray()[0];
switch(cmdType)
{
case 'h':
Task.Run(Home);
break;
//...the rest of the commands...
}
}
}
Код: Выделить всё
static async Task Home()
{
Console.WriteLine("Running Task Home()");
WriteMyCommand(2, 0, serialPort); //this function is proven working. Writes the command to the arduino.
Console.WriteLine("awaiting homeRelease...");
await homeRelease.Task;
Console.WriteLine("...homeRelease Received");
homed = true;
homeRelease.SetResult(false);
}
Код: Выделить всё
public static void serialPort_ReadArduinoData(object sender, SerialDataReceivedEventArgs e)
{
SerialPort spL = (SerialPort)sender;
byte[] buf = new byte[spL.BytesToRead];
spL.Read(buf,0,buf.Length);
newDataContent = $"{System.Text.Encoding.ASCII.GetString(buf)}";
Console.WriteLine($"Received: {newDataContent}");
switch(newDataContent[1])
{
case '2': //response Home command
Console.WriteLine("Detected home response");
homeRelease.SetResult(true);
break;
//rest of switch statement
}
}
Есть ли такое? как я мог бы заставить несколько этих потоков/задач/заданий ждать отдельного флага, поднятого оператором переключения в сериальномПорт_ReadArduinoData, который позволит им продолжить работу? Или этот подход просто ненормальный?
Я совершенно не понимаю, куда мне двигаться дальше. Буду очень признателен за любую помощь: срок у меня уже истек, а к тому же я не профессиональный программист.
Подробнее здесь: https://stackoverflow.com/questions/787 ... ads-to-wai