加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net – 随机字符串生成器在多个调用中创建相同的字符串

发布时间:2020-12-16 03:32:58 所属栏目:asp.Net 来源:网络整理
导读:我已经构建了一个随机字符串生成器,但是我遇到了一个问题,如果我在Page_Load方法中多次调用该函数,该函数将返回相同的字符串两次. 这是代码 Public Class CustomStrings ''' summary' ''' Generates a Random String' ''' /summary' ''' param name="n"numbe
我已经构建了一个随机字符串生成器,但是我遇到了一个问题,如果我在Page_Load方法中多次调用该函数,该函数将返回相同的字符串两次.

这是代码

Public Class CustomStrings
    ''' <summary>'
    ''' Generates a Random String'
    ''' </summary>'
    ''' <param name="n">number of characters the method should generate</param>'
    ''' <param name="UseSpecial">should the method include special characters? IE: #,$,!,etc.</param>'
    ''' <param name="SpecialOnly">should the method include only the special characters and excludes alpha numeric</param>'
    ''' <returns>a random string n characters long</returns>'
    Public Function GenerateRandom(ByVal n As Integer,Optional ByVal UseSpecial As Boolean = True,Optional ByVal SpecialOnly As Boolean = False) As String

        Dim chars As String() ' a character array to use when generating a random string'
        Dim ichars As Integer = 74 'number of characters to use out of the chars string'
        Dim schars As Integer = 0 ' number of characters to skip out of the characters string'

        chars = { _
         "A","B","C","D","E","F",_
         "G","H","I","J","K","L",_
         "M","N","O","P","Q","R",_
         "S","T","U","V","W","X",_
         "Y","Z","0","1","2","3",_
         "4","5","6","7","8","9",_
         "a","b","c","d","e","f",_
         "g","h","i","j","k","l",_
         "m","n","o","p","q","r",_
         "s","t","u","v","w","x",_
         "y","z","!","@","#","$",_
         "%","^","&","*","(",")",_
         "-","+"}


        If Not UseSpecial Then ichars = 62 ' only use the alpha numeric characters out of "char"'
        If SpecialOnly Then schars = 62 : ichars = 74 ' skip the alpha numeric characters out of "char"'

        Dim rnd As New Random()
        Dim random As String = String.Empty
        Dim i As Integer = 0
        While i < n
            random += chars(rnd.[Next](schars,ichars))
            System.Math.Max(System.Threading.Interlocked.Increment(i),i - 1)
        End While
        rnd = Nothing
        Return random
    End Function
End Class

但如果我打电话给这样的话

Dim rnd1 As New CustomStrings
    Dim rnd2 As New CustomStrings

    Dim str1 As String = rnd1.GenerateRandom(5) 
    Dim str2 As String = rnd2.GenerateRandom(5) 

    rnd1 = Nothing
    rnd2 = Nothing

响应将是这样的

g*3Jq
g*3Jq

我第二次打电话给它,它会

3QM0$
3QM0$

我错过了什么?我希望每个随机字符串都生成为唯一的.

解决方法

这样做的原因是,当你构造一个Random类的实例时,它会从时钟中自行播种,但是如果你快速连续调用它,那么这个时钟的准确性不足以在每次调用时生成一个新的种子.

换句话说,这个:

Random r = new Random();
int i = r.Next(1000);
r = new Random();
int j = r.Next(1000);

在i和j中产生相同值的概率非常高.

你需要做的是:

>创建并缓存Random实例,以便它与每次调用使用的实例相同(但不幸的是,该类不是线程安全的,因此至少为每个线程保留一个缓存副本)
>使用每次调用更改的内容对其进行播种(这有点困难,因为使用顺序值对其进行播种将产生可预测的随机数)

这是一个示例程序,它为每个线程创建一个单独的Random实例,并从全局随机对象中播种这些实例.同样,这可能会产生可预测的序列.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace SO2755146
{
    public class Program
    {
        public static void Main()
        {
            List<Task> tasks = new List<Task>();
            for (int index = 0; index < 1000; index++)
                tasks.Add(Task.Factory.StartNew(() => Console.Out.WriteLine(RNG.Instance.Next(1000))));
            Task.WaitAll(tasks.ToArray());
        }
    }

    public static class RNG
    {
        private static Random _GlobalSeed = new Random();
        private static object _GlobalSeedLock = new object();

        [ThreadStatic]
        private static Random _Instance;

        public static Random Instance
        {
            get
            {
                if (_Instance == null)
                {
                    lock (_GlobalSeedLock)
                    {
                        _Instance = new Random(_GlobalSeed.Next());
                    }
                }
                return _Instance;
            }
        }
    }
}

如果您只想从时钟中为每个随机实例播种,但至少每个线程生成随机序列,您可以像这样简化它:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace SO2755146
{
    public class Program
    {
        public static void Main()
        {
            List<Task> tasks = new List<Task>();
            for (int index = 0; index < 1000; index++)
                tasks.Add(Task.Factory.StartNew(() => Console.Out.WriteLine(RNG.Instance.Next(1000))));
            Task.WaitAll(tasks.ToArray());
        }
    }

    public static class RNG
    {
        [ThreadStatic]
        private static Random _Instance;

        public static Random Instance
        {
            get
            {
                if (_Instance == null)
                    _Instance = new Random();

                return _Instance;
            }
        }
    }
}

这可能会使两个线程彼此非常接近地以相同的值播种,因此需要进行权衡.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读