|
2 | 2 | using System.Collections.Generic;
|
3 | 3 | using System.IO.Ports;
|
4 | 4 | using System.Threading;
|
| 5 | +using System.Threading.Tasks; |
5 | 6 |
|
6 | 7 | namespace Bonsai.Arduino
|
7 | 8 | {
|
@@ -90,7 +91,6 @@ public Arduino(string portName, int baudRate)
|
90 | 91 | commandBuffer = new byte[MaxDataBytes];
|
91 | 92 | sysexBuffer = new byte[MaxDataBytes];
|
92 | 93 | readBuffer = new byte[serialPort.ReadBufferSize];
|
93 |
| - serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived); |
94 | 94 | }
|
95 | 95 |
|
96 | 96 | /// <summary>
|
@@ -141,28 +141,62 @@ void OnSysexReceived(SysexReceivedEventArgs e)
|
141 | 141 | SysexReceived?.Invoke(this, e);
|
142 | 142 | }
|
143 | 143 |
|
144 |
| - void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) |
| 144 | + Task RunAsync(CancellationToken cancellationToken) |
145 | 145 | {
|
146 |
| - var bytesToRead = serialPort.BytesToRead; |
147 |
| - while (serialPort.IsOpen && bytesToRead > 0) |
| 146 | + serialPort.Open(); |
| 147 | + Thread.Sleep(ConnectionDelay); |
| 148 | + serialPort.ReadExisting(); |
| 149 | + return Task.Factory.StartNew(() => |
148 | 150 | {
|
149 |
| - var bytesRead = serialPort.Read(readBuffer, 0, Math.Min(bytesToRead, readBuffer.Length)); |
150 |
| - for (int i = 0; i < bytesRead; i++) |
| 151 | + using var cancellation = cancellationToken.Register(serialPort.Dispose); |
| 152 | + while (!cancellationToken.IsCancellationRequested) |
151 | 153 | {
|
152 |
| - ProcessInput(readBuffer[i]); |
| 154 | + try |
| 155 | + { |
| 156 | + var bytesToRead = serialPort.BytesToRead; |
| 157 | + if (bytesToRead == 0) |
| 158 | + { |
| 159 | + var nextByte = serialPort.ReadByte(); |
| 160 | + if (nextByte < 0) break; |
| 161 | + ProcessInput((byte)nextByte); |
| 162 | + } |
| 163 | + else |
| 164 | + { |
| 165 | + while (bytesToRead > 0) |
| 166 | + { |
| 167 | + var bytesRead = serialPort.Read(readBuffer, 0, Math.Min(bytesToRead, readBuffer.Length)); |
| 168 | + for (int i = 0; i < bytesRead; i++) |
| 169 | + { |
| 170 | + ProcessInput(readBuffer[i]); |
| 171 | + } |
| 172 | + bytesToRead -= bytesRead; |
| 173 | + } |
| 174 | + } |
| 175 | + } |
| 176 | + catch (Exception) |
| 177 | + { |
| 178 | + if (!cancellationToken.IsCancellationRequested) |
| 179 | + { |
| 180 | + throw; |
| 181 | + } |
| 182 | + break; |
| 183 | + } |
153 | 184 | }
|
154 |
| - bytesToRead -= bytesRead; |
155 |
| - } |
| 185 | + }, |
| 186 | + cancellationToken, |
| 187 | + TaskCreationOptions.LongRunning, |
| 188 | + TaskScheduler.Default); |
156 | 189 | }
|
157 | 190 |
|
158 | 191 | /// <summary>
|
159 | 192 | /// Opens a new serial port connection to the Arduino board.
|
160 | 193 | /// </summary>
|
161 |
| - public void Open() |
| 194 | + /// <param name="cancellationToken"> |
| 195 | + /// A <see cref="CancellationToken"/> which can be used to cancel the operation. |
| 196 | + /// </param> |
| 197 | + public void Open(CancellationToken cancellationToken = default) |
162 | 198 | {
|
163 |
| - serialPort.Open(); |
164 |
| - Thread.Sleep(ConnectionDelay); |
165 |
| - serialPort.ReadExisting(); |
| 199 | + RunAsync(cancellationToken); |
166 | 200 | }
|
167 | 201 |
|
168 | 202 | void ReportInput(ref int[] reportInput, byte command, int index, bool state)
|
|
0 commit comments