There is a cyclic buffer that is continuously filled in the background thread. I need to read it once a second and update the UI interface. Questions related to this.

  1. Using async / await to fill the buffer, is this correct?

    public async Task ReceiveAsync(CancellationToken ct) { await Task.Run(() => Receive(progressData)); //в Receive() происходит получение пакетов/разбор из сети и запись в цикличный буфер. } 
  2. Updating the UI once a second, I imagine this: transferring data through IProgress :

     IProgress<DTO> progressData = new Progress<DTO>(progressHandler); 

    It seems to me that this method is not entirely correct, it can be read directly from the UI stream, this buffer which is filled in another stream. But then another question, reading and writing at the same time? Will there be any problems with this.

  • Show what you have inside Receive() . - andreycha
  • Is receiving packets / parsing from the network a completely synchronous code? - andreycha
  • @andreycha, yes, so I run it in a separate thread. - Gardes

1 answer 1

On the first point there are a few comments:

  1. Inside Receive() you have a loop. How will you interrupt him? Do not forget to transfer the CancellationToken inside, as well as to launch the task itself:

     public async Task ReceiveAsync(CancellationToken ct) { await Task.Run(() => Receive(progressData, ct), ct); } 
  2. Do you expect somewhere at the top of a task that returns ReceiveAsync() ? If not, there may be problems with exceptions. Or handle exceptions inside Receive() .

  3. The async / await keywords are redundant in this case, you can omit them and simply return the task:

     public Task ReceiveAsync(CancellationToken ct) { return Task.Run(() => Receive(progressData, ct), ct); } 

On the second point: IProgress<T> is the most correct way to notify the UI of changes. In addition, it is a thread safe method. If you can beautifully enclose information about what has changed, then use it.

If every time you just send a new piece of your buffer to the UI, then it may be worthwhile to think about the UI reading the updates on its own. Plus you mentioned that the update should occur once a second, and this may already be impossible for the Receive() logic. And there can be no pollution of the logic of reading from the network with the logic of the timer.

If you access the buffer directly from the UI (or any other stream), you will need to synchronize access to it: using lock or ReadWriteLockSlim , if you can have several readers.

  • Thanks for the tips on the first item. When reading from the UI, is it necessary to synchronize threads? At the moment I did without synchronization. How it works for me: the buffer class is wrapped in another class T, then the List <T> is bound to the UI. those. I add a new T object via Dispather Invoke. And already when reading the buffer from the UI stream, no manipulations with the dispatcher, etc. I do not, is this the right approach? PS I have one reader. - Gardes
  • @Gardes if type T immutable for you, then there will be no problem. - andreycha