Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么类实例值在多线程环境中损坏?_C#_Multithreading - Fatal编程技术网

C# 为什么类实例值在多线程环境中损坏?

C# 为什么类实例值在多线程环境中损坏?,c#,multithreading,C#,Multithreading,下面是简单的代码 class Program { static void Main(string[] args) { for (int i = 0; i < 100; i++) { Thread thread = new Thread(new ThreadStart(()=> SimpleClass.Instance.weird.SetHello(i))); thread.Start();

下面是简单的代码

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            Thread thread = new Thread(new ThreadStart(()=> SimpleClass.Instance.weird.SetHello(i)));
            thread.Start();
        }

        Console.Read();
    }
}

interface IClass
{
    WeirdClass weird{ get; set; }
}

class SimpleClass : IClass {
    public static SimpleClass Instance = new SimpleClass();

    public WeirdClass weird{ get; set; }

    public SimpleClass()
    {
        weird= new WeirdClass();
    }
}

class WeirdClass
{
    public int hello;

    public void SetHello(int i)
    {
        this.hello = i;
        Console.WriteLine(this.hello);
    }
}
类程序
{
静态void Main(字符串[]参数)
{
对于(int i=0;i<100;i++)
{
Thread-Thread=new-Thread(new-ThreadStart(()=>SimpleClass.Instance.wird.SetHello(i));
thread.Start();
}
Console.Read();
}
}
接口类
{
古怪类古怪{get;set;}
}
类SimpleClass:IClass{
公共静态SimpleClass实例=新SimpleClass();
公共古怪类古怪{get;set;}
公共SimpleClass()
{
怪异=新的古怪类();
}
}
阶级怪人阶级
{
公共int你好;
公共void SetHello(int i)
{
this.hello=i;
Console.WriteLine(this.hello);
}
}
我们可以看到,WeirdClass中的“hello”值在多线程中是不正确的,该值就像一个静态实例,但事实并非如此


也许魔法发生在
SimpleClass.Instance.async
上,有人能给我解释一下吗?谢谢

我对你的问题投了赞成票,因为它给我带来了一些有趣的研究

在for循环中,将
i
变量分配给temp
ii
并在线程初始化中使用
ii
,如下所示:

var ii = i;
Thread thread = new Thread(
    new ThreadStart(()=> SimpleClass.Instance.async.SetHello(ii)));
thread.Start();
我用不同的配置和不同的上下文对它进行了测试(例如,在
hello
分配和
Console.WriteLine
之间放置一个随机
Thread.Sleep

我的解决方案是这样的:每个线程都有自己独特的
i
,并将其一次性写入
控制台。
但是这些数字不是按顺序写的,因为创建线程时线程不会按顺序开始

只是附带说明:正如@JonSkeet所建议的,不要使用
async
作为标识符,它是一个保留字。请改用
asyncywird
InnerClass
HelloContainer
,或者任何不是官方C#标记的东西,否则代码就会变得不那么清晰

更新-解决方案:

这:

for(int i=0;i<10;i++)
相当于:

int i;
for(i = 0; i < 10; i++)
inti;
对于(i=0;i<10;i++)
也就是说,在这两种情况下,
i
都是在
for
循环之外创建的,因此它以某种方式在循环的不同循环之间共享。如果您检查提供的@CodeCaster链接,您将看到以前版本的C#的
foreach
循环存在相同的问题

如果以
i
作为输入在循环中声明线程,则告诉线程:“好,开始时,获取
i
值!”。此时,
i
具有适当的值,但线程只有在有效启动时才会请求
i
,因此该值已经更改,因为在此期间,主线程已经开始了新的循环周期,并且已经为下一次迭代重新分配了
i

相反,如果在循环内部创建一个临时变量
ii
,它将保持在该循环中,并且在外部看不到


这是整个游戏的演示:尝试在循环之外声明
ii
。。。该行为同样是不正确的,您使用
i
变量显示了该行为。

请阅读并明确说明。它是如何“腐败”的?你知道你正在使用一个
WeirdClass
实例吗?我还强烈建议不要使用
async
作为标识符,因为它是一个上下文关键字…无论如何,你正在访问一个闭包,请看。是的,你的代码给了我正确的结果。。。。区别是什么……如果你想发布一个有用且正确的答案,你必须阅读。@MK87:新版本的C#编译器改变了这种行为。请注意,它由用于构建项目的.NET编译器版本决定,而不是运行时兼容性问题。
int i;
for(i = 0; i < 10; i++)