使用List的内容初始化线程 [英] Initializing a thread using the contents of List

查看:113
本文介绍了使用List的内容初始化线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,



我的代码如下:



Hello,

I have a code which looks like this :

        static void Main(string[] args)
        {
            List<string> l = new List<string>(250);
            List<thread> t = new List<thread>(250);


    l.Add("a");
    l.Add("b");
    l.Add("c");

    for (int i = 0; i<l.count;i++>            {

                t[i] = new Thread(()=>work(l[i]));  ///Index out of range exception occurrd at this line
                t[i].IsBackground = true;
                t[i].Start();
                
            }

  

    Console.ReadLine();


}

static void work(string data)
{
    Console.WriteLine(data);
}



///如果说:t [i] = new Thread(()=该异常消失> work(l [i-1]));

///但它是一个bug并且不能正确处理记录。



请帮助



添加代码块 - OriginalGriff [/ edit]


/// That exception goes away if is say : t[i] = new Thread(()=>work(l[i-1]));
/// But its a bug and does not process records properly.

Please help

[edit]Code block added - OriginalGriff[/edit]

推荐答案

首先,如果您要发布代码,然后发布 完全 提供问题的代码 - 复制并粘贴它。您显示的片段不是:它不会编译,因为就C#而言,thread与Thread不同。当你重新输入它以最终得到类似的东西时可能会或可能不会显示问题。



问题是事情开始变得有点毛茸茸当你使用线程和匿名委托时 - 因为线程在你认为它们不会执行时,如果你开始将变量传递给委托,你需要确定你传递的是什么...



试试这个(它是你的缩减版本:

First off, if you are going to post code, then post exactly the code that give you the problem - copy and paste it. The fragment you show isn't that: it won't compile because "thread" is not the same as "Thread" as far as C# is concerned. When you re-type it to end up with "something similar" which may or may not demonstrate the problem.

The problem is that things start to get a little hairy when you play with threads and anonymous delegates - because threads do not execute when you think they will, and if you start passing variable to delegates, you need to be sure what you are passing...

Try this instead (It's a cut down version of yours:
static void Main(string[] args)
    {
    List<string> l = new List<string>(250);
    l.Add("a");
    l.Add("b");
    l.Add("c");

    for (int i = 0; i < l.Count; i++)
        {
        string s = l[i];
        Console.WriteLine("UI Thread: {0}:{1}", i, s);
        Thread nt = new Thread(() => Console.WriteLine("Delegate : {0}:{1}", i, s));
        nt.IsBackground = true;
        nt.Start();
        }
    Console.ReadLine();
    }

看看你得到了什么:

And look what you get:

UI Thread: 0:a
UI Thread: 1:b
UI Thread: 2:c
Delegate : 2:a
Delegate : 2:b
Delegate : 3:c



什么?这是怎么发生的?

非常简单:整数是一种值类型,这意味着变量本身被传递给委托而不是对变量的引用。因此,它不是传递的包含数字,它是保存值的变量。这意味着在线程本身运行之前不会检查它保存的值 - 这可能是在调用Thread.Start方法之后的任何时间,具体取决于您拥有的核心数量以及系统中的其他核心数量。时间。



在你的代码中,这意味着直到循环结束后才检索到i的值,这意味着它超出了列表 - 你得到一个例外。



想看看如何治愈这个?


What? How did that happen?
Pretty simple: the integer is a Value type, which means that the variable itself is passed to the delegate rather than a reference to the variable. So it isn't the number it "contains" that is passed, it is the variable that holds the value. Which means that the value it holds is not examined until the thread itself runs - which may be at any time after the Thread.Start method has been called, depending on how many cores you have and whet else is going on in the system at that time.

In your code, that means that the value of "i" is not retrieved until after the loop ends sometimes, which means that it is outside the range of the list - and you get an exception.

Want to see how to "cure" this?

static void Main(string[] args)
    {
    List<string> l = new List<string>(250);
    l.Add("a");
    l.Add("b");
    l.Add("c");

    for (int i = 0; i < l.Count; i++)
        {
        string s = l[i];
        Console.WriteLine("UI Thread: {0}:{1}", i, s);
        int j = i;
        Thread nt = new Thread(() => Console.WriteLine("Delegate : {0}:{1}:{2}",i, j, s));
        nt.IsBackground = true;
        nt.Start();
        }
    Console.ReadLine();
    }

现在运行......:笑:







先生,

疑问:
下面的
只是一个伪代码:一个泛型类,只有在type参数为的时候才会创建它的构造函数一个枚举。



Now run that...:laugh:



"Sir,
A doubt:
below is just a pseudo code: a generic class, its constructor will be created only if the type parameter is an Enum.

class custom_dictionary<t>
     {
         static public custom_dictionary()////this statement could be wrong
         {
              if(!typeOf(T).IsEnum)
                 ////throw new argument not enum exception
         }

}







- 我在这里使用了一个静态构造函数,如果我使用了一个实例构造函数呢?

- H两者有什么不同?以及检查类型是否为Enum的约束怎么办?



谢谢,

- Rahul




First off,静态构造函数是否会起作用?想一想:什么时候执行静态构造函数,多久一次,如果你有两个不同枚举的类实例会发生什么?



其次,在编译时有一种机制:通用约束:




- I have used a static constructor here, what if i used an instance constructor?
- How do both vary from each other? and what about constraints to check if the type is Enum?

Thanks,
- Rahul"


First off, Is a static constructor going to work? Think about it: when is a static constructor executed, how often, and what happens if you have two instances of your class with different enums?

Second, there is a mechanism for doing that at compile time: Generic Constraints:

public class custom_dictionary<T> where T : Enum
    {
    }

这对编译器说的是:这是一个泛型类,但我只能使用枚举:如果他试图用int或文本框声明我,请告诉他不要打扰

确实如此:

What that does is says to the compiler: "This is a generic class, but I can only work with enums: if he tries to declare me with an int or a Textbox, tell him not to bother"
And it does:

custom_dictionary<StringSplitOptions> cd = new custom_dictionary<StringSplitOptions>();

没问题,但是

Is fine, but

custom_dictionary<int> cd = new custom_dictionary<int>();

会给你一个没有拳击转换编译错误。



这比尝试在运行时执行此操作要好很多,因为它会将检查移动到编译器中 - 因此您的问题会更早出现:在编写之前几天,你必须在第一次测试时扔掉它!

Will give you a "there is no boxing conversion" compiler error.

This is a lot, lot better than trying to do this at run time, because it moves the checking into the compiler - so your problem shows up much earlier: before you have coded for a couple of days and have to throw it all away the first time you test it!


这篇关于使用List的内容初始化线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆