Continuous polling using Tasks

冷暖自知 提交于 2020-02-21 13:35:50

问题


This is something I've always used Threads / BackgroundWorker for, but am trying to migrate over to Task way of doing things.

Let's say I have a 3rd party SDK I use to read bytes from a USB port. That read call is blocking and times out after 100 ms if no bytes are read, returning null. It returns immediately if bytes are read, returning byte[] array of read bytes.

So I basically need to keep polling over and over, and take action on received bytes, by calling Parsing function. It's a WPF application, so the returned bytes should be able to be passed to a UI thread function.

What's the right approach to doing this? This is what I have so far, and it seems to work, but I want to make sure it's the right way of doing things using 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;
}

回答1:


Looks ok to me, just 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 store this

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

Finally call your function like this

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

This way you can cancel your task in any moment by calling

tokenSource.Cancel()

Alternatively, if you don't want to use Tasks, you can spawn a new Thread and pass in the Dispatcher object. In this way, the newly created Thread can fire stuff onto the UI Thread safely.




回答2:


Since your polling task might run for a long time, you should think about running it in a dedicated thread.

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

like this:

Task<byte[]> readBytesTask = Task.Factory.StartNew(() =>
    {
        byte[] bytes;

        do
        {
            bytes = ReadBytes();
        } while (bytes == null);

        return bytes;
    }, TaskCreationOptions.LongRunning);


来源:https://stackoverflow.com/questions/41635578/continuous-polling-using-tasks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!