C# - Есть ли способ заставить несколько асинхронных методов (задач или потоков) ждать, пока не возникнут определенные отC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 C# - Есть ли способ заставить несколько асинхронных методов (задач или потоков) ждать, пока не возникнут определенные от

Сообщение Anonymous »

Я пытаюсь заставить систему вызова/ответа работать с Arduino, управляющим механизмом через последовательный порт.
Управляющий компьютер создает задачу/поток, который обрабатывает каждое задание, назначенное ему. arduino асинхронно (приведение механизма в исходное положение, установка положения, перемещение и т. д.) arduino сообщает, как он выполняет каждое задание ("успешно размещено", "перемещено в положение" и т. д.), что позволяет продолжить выполнение задания его путь к коду.
Однако все, что я пробовал, имеет некоторые проблемы, поэтому мне нужен совет, как действовать.
Вот что я пробовал. (Не стесняйтесь спрашивать об этом подробнее.)
  • Код: Выделить всё

    while(!doneWaiting){thread.sleep(5);}
    зацикливается, когда я использовал систему на основе потоков вместо системы, основанной на задачах. Это съедало весь процессор, когда у меня было несколько потоков, ожидающих ответа от Arduino (например, я пытался переместить MoveAxis1 и moveAxis4 одновременно, и оба ждали разрешения на продолжение, что приводило к сбою программы из-за перегрузки). использование памяти.)
  • Неоднократный анализ входных данных 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...

}
}
}
Вот как выглядит главная задача. Он приостанавливается посередине с помощью `homeRelease.Task;` и ожидает завершения.

Код: Выделить всё

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);
}
Событие SerialData_ReadArduinoData выглядит следующим образом:

Код: Выделить всё

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
}
}
Когда я выполняю одну команду «Home», система работает как положено и приостанавливает выполнение задачи «Home» в ожидании до тех пор, пока не будет получен сигнал «arduino has homeed». Однако когда я запрашиваю еще один экземпляр того же задания, я получаю сообщение об ошибке: «Была предпринята попытка перевести задачу в конечное состояние, когда она уже завершена».
Есть ли такое? как я мог бы заставить несколько этих потоков/задач/заданий ждать отдельного флага, поднятого оператором переключения в сериальномПорт_ReadArduinoData, который позволит им продолжить работу? Или этот подход просто ненормальный?
Я совершенно не понимаю, куда мне двигаться дальше. Буду очень признателен за любую помощь: срок у меня уже истек, а к тому же я не профессиональный программист.

Подробнее здесь: https://stackoverflow.com/questions/787 ... ads-to-wai
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»