Continuous task polling

This is what I always used Threads / BackgroundWorker, but trying to switch to a way to complete tasks.

Say I have a third-party SDK that I use to read bytes from a USB port. This read call is blocked and expires after 100 ms if no bytes are read, returning null. It returns immediately if bytes are read, returning a byte [] array of bytes read.

Therefore, I basically need to continue polling again and again, and take action on the received bytes by calling the Parsing function. This is a WPF application, so the bytes returned must be passed to the UI thread function.

What is the right approach to this? This is what I have so far, and it seems to work, but I want to make sure that this is the right way to do things with TPL:

private void _connectUsbButton_Click(object sender, RoutedEventArgs e) { ListenForUsbMessagesAsync(); } private async void ListenForUsbMessagesAsync() { while (true) { byte[] readBytes = await ReadBytesAsync(); Parse(readBytes); } } private Task<byte[]> ReadBytesAsync() { Task<byte[]> readBytesTask = Task.Run(() => { byte[] bytes; do { bytes = ReadBytes(); } while (bytes == null); return bytes; }); return readBytesTask; } private byte[] ReadBytes() { byte[] readBytes = _usbSdk.ReadBytes(); //100ms timeout (returns null if no bytes read) return readBytes; } 
+5
source share
2 answers

It looks good, just a few suggestions here:

 private async Task ListenForUsbMessagesAsync(CancellationToken token) { while (true) { byte[] readBytes = await ReadBytesAsync(); Parse(readBytes); token.ThrowIfCancellationRequested(); } } 

Somewhere else, like in WPF Window.ctor, save this

 var tokenSource = new System.Threading.CancellationTokenSource(); 

Finally call your function as follows

  private void _connectUsbButton_Click(object sender, RoutedEventArgs e) { ListenForUsbMessagesAsync(tokenSource.Token); } 

This way you can cancel your task at any time by calling

 tokenSource.Cancel() 

Alternatively, if you do not want to use Tasks, you can create a new thread and pass a Dispatcher object. In this way, the newly created stream can safely write material to the user interface stream.

+4
source

Since your polling task can work for a long time, you should consider running it in a dedicated thread.

you can achieve this by passing the TaskCreationOptions.LongRunning flag when creating a polling task.

like this:

 Task<byte[]> readBytesTask = Task.Factory.StartNew(() => { byte[] bytes; do { bytes = ReadBytes(); } while (bytes == null); return bytes; }, TaskCreationOptions.LongRunning); 
+5
source

Source: https://habr.com/ru/post/1262742/


All Articles