C# 从异步方法返回相同的值

C# 从异步方法返回相同的值,c#,random,async-await,C#,Random,Async Await,我现在对这件事视而不见,所以请帮帮我 当我在循环中调用此方法两次时,它返回相同的值。为什么? public async Task<int> RollDice() { var rnd = new Random(); var selected = 0; await Task.Run(() => { selected = rnd.Next(1, 6); }); return selected; } public异步

我现在对这件事视而不见,所以请帮帮我

当我在循环中调用此方法两次时,它返回相同的值。为什么?

public async Task<int> RollDice() {
    var rnd = new Random();
    var selected = 0;

    await Task.Run(() => {
        selected = rnd.Next(1, 6);
        });

    return selected;
}
public异步任务RollDice(){
var rnd=新随机数();
选择的var=0;
等待任务。运行(()=>{
所选=rnd.Next(1,6);
});
返回选中的;
}

您必须在方法之外初始化
随机
对象,以防止它使用相同的种子反复初始化,从而返回相同的值


正如LukeH在评论中正确添加的那样,需要注意的是,
System.Random
类不是线程安全的,不应该在单独线程中的任务之间共享。

您使用的是
Random
类的两个实例。使用,使用基于系统时钟的值对随机数生成器进行种子设定

这意味着,如果您正在创建两个紧随其后的
随机
实例,它们将使用相同的值进行初始化,因为系统时钟的分辨率是有限的。拥有相同的种子意味着这两个实例将产生相同的结果序列


一些谷歌搜索显示,使用
Random
交叉线程可能会导致它中断并返回一个无休止的零序列,因此,如果您必须对代码的这一特定部分进行多线程处理,您可能希望了解如何创建
Random
类的单线程安全版本

没错,但是。。。请注意,
System.Random
不是线程安全的,因此在多个线程池任务之间共享一个实例(通过
Task.Run
)不是一个好主意。我编辑了代码,因此Random是静态的。私有静态随机rnd=新随机();public async Task RollDice(){var selected=0;wait Task.Run(()=>{selected=rnd.Next(1,6);});return selected;}缺少线程安全性可能会导致此类生成随机结果。。。哦,等等:通过@danielovich,由于线程安全问题,您发布的修订代码不推荐。请参阅我答案中链接的文章,了解解决方法。因此,我将添加一个锁。Thx@Thorarin