В момента нашето приложение се свързва с Arduino през сериен порт. Изпращаме някои ASCII-форматирани команди и получаваме същото в замяна. За да направим това, имаме опашка от команди, нишка, посветена на писането на тези команди в порта, и нишка, посветена на четенето и обработката на всички входящи отговори. Самият клас е отговорен за изпращането на отговорите, което му дава твърде голяма отговорност (трябва да отговаря само за пристанищните операции, а не за бизнес логиката).
Предпочитаме да направим това по асинхронен начин. Всичко в системата може да изпрати команда с функция за обратно извикване и изчакване. Ако серийният порт получи правилен отговор, той извиква функцията за обратно извикване. В противен случай времето за изчакване изтича и може би извиква второ обратно извикване (или евентуално едно обратно извикване с флаг succeeded?
).
Ние обаче сме използвали само асинхронни методи (особено в уеб операции), а не сме писали такава система. Може ли някой да ни даде насоки как да продължим?
Текущият ни план е да съхраняваме опашка от тези команди. При всеки отговор, ако бъде намерена свързана команда (чрез сравняване на ASCII стойности), тя се изважда от опашката и се изпълнява обратното извикване. Таймерът периодично ще проверява за изчакване, ще излиза от опашката и ще изпълнява подходящото обратно извикване. Изглежда като просто решение, но количеството код за поддръжка на това се увеличава значително и искахме да сме сигурни, че няма по-добри вградени решения или най-добри практики за това.
Редактиране: За да изясним допълнително, този конкретен клас е сингълтон (за добро или лошо) и има много други работещи нишки, които могат да имат достъп до него. Например една нишка може да иска да поиска стойност на сензор, докато друга нишка може да управлява мотор. Тези команди и свързаните с тях отговори не се случват по линеен начин; времето може да бъде обърнато. Следователно традиционен модел производител-потребител не е достатъчен; това е по-скоро диспечер.
Например, нека наречем този единичен клас Arduino
. Thread A
работи и иска да изпрати команда "*03"
, така че извиква Arduino.Instance.SendCommand("*03")
. Междувременно Thread B
изпраща команда "*88"
, като и двете се изпращат в почти реално време. Малко по-късно нишката SerialPort.Read()
на Arduino
взима отговор за *88
и след това отговор за *03
(т.е. в обратния ред, в който са изпратени). Как да позволим както на Thread A
, така и на Thread B
да блокират правилно в очакване на конкретния отговор? Предполагаме, че ще използваме AutoResetEvent
вътре във всяка нишка, с асинхронно обратно извикване, за да ни позволи да го .Set
.