The documentation for RNGCryptoServiceProvider states:
This type is thread safe.
Your code does not show that RNGCryptoServiceProvider not thread safe, since you are using the same array in multiple threads. Reusing this array is not thread safe, even if RNGCryptoServiceProvider .
Regarding performance, I want to note that creating a new instance of RNGCryptoServiceProvider very cheap. The dear part is the overhead for each GetBytes call.
So, if you have performance problems, the first thing I will try is to ask for more data at a time and break it myself. If this is still not enough, use the stream cipher planted by the CSPRNG system.
source share