private int index = 0;
        private object threadlock = new object();
        private void button1_Click(object sender, EventArgs e)
        {
            // 保存1000个文件路径
            List<string> lstPath = new List<string>();
            for (int i = 0; i < 1000; i++)
            {
                lstPath.Add("c:\\test\\"+ i.ToString() +".exe");
            }            index = 0;
            Thread[] threads = new Thread[10];
            for (int i = 0; i < threads.Length; i++)
            {
                threads[i] = new Thread(new ParameterizedThreadStart(GetFileData));
                threads[i].IsBackground = true;
            }            foreach (Thread t in threads)
            {
                t.Start(lstPath);
            }            foreach (Thread t in threads)
            {
                t.Join();
            }
        }        private void GetFileData(object objPath)
        {
            if (objPath == null)
            {
                return;
            }            List<string> lstPath = (List<string>)objPath;
            if (lstPath == null || lstPath.Count <= 0)
            {
                return;
            }            while (true)
            {
                string strFile = "";
                if (index >= lstPath.Count)
                {
                    return;
                }                // ReadFile阻塞的时间非常长,所以我不想使用lock来同步ReadFile
                // 但是,如果不用lock来同步ReadFile,好像数组又不对了
                // 我的想法,只有 strFile = lstPath[index] 这行代码涉及到同步处理
                // 只要使用lock处理取出正确的path,ReadFile是可以不用lock的吧
                // 如果ReadFile也使用了lock,其他线程都必须等待前一个线程结束,才能继续
                // 这样不又变成单线程了吗??
                lock (threadlock)
                {
                    strFile = lstPath[index];
                    // ReadFile(strFile);
                }
                ReadFile(strFile);
            }
        }

解决方案 »

  1.   

    index 是资源关键,index++ 抽出来加锁
      

  2.   

    你的分析是对的。lock 相当于一个独木桥。虽然还是多线程,但是却不是并发的了。
      

  3.   

    晕,上面的测试代码忘记index++了,应该是下面这样
    第一种情况
    lock (threadlock)
    {
       strFile = lstPath[index++];
    }
    ReadFile(strFile);第二种情况
    lock (threadlock)
    {
     strFile = lstPath[index++];
     ReadFile(strFile);
    }第一种情况,数据仍然有错误
    第二种情况,数据是正确的
      

  4.   


    也就是说,为了提高速度,ReadFile是不能加lock了
      

  5.   

    算多线程
    至于怎么处理线程运行次序是另一回事
    不过你的处理也不对,你不能保证每个线程使用不同的文件路径,因为index一直没有变化,所以strFile也不会变化。如果文件不是共享方式,多个线程访问同一个文件会抛出异常。
      

  6.   

    我们可以作个假设:
    不参考CPU因素,不参考调度问题的时间损耗
    现在共有10个文件,开了10个线程,读一个文件需要10秒
    单线程需要100秒读取完
    如果是下面第一种情况,只需要10秒
    如果是下面第二种情况,还是需要100秒
    对吗?lock (threadlock) 

    strFile = lstPath[index++]; 

    ReadFile(strFile);第二种情况
    lock (threadlock) 

    strFile = lstPath[index++]; 
    ReadFile(strFile); 
    }
      

  7.   

    index 锁了就没问题。
    除非你ReadFile里还做了什么事不过你的代码:
    if (index >= lstPath.Count)
    {
         return;
    }
    应该放到lock里,否则有异常。
      

  8.   

    lz没想明白只同步Index就能保证是安全的?class Program
    {
        static List<string> _files;
        static int _index = 0;
        static object _lock = new object();    static void Main(string[] args)
        {
            _files = Enumerable.Range(0, 40).Select(i => "File" + i).ToList();
            var t1 = new Thread(DoWork);
            var t2 = new Thread(DoWork);
            t1.Start();
            t2.Start();
            Console.Read();
        }    static void DoWork()
        {
            while (true)
            {
                var filename = "";
                lock (_lock)
                {
                    if (_index >= _files.Count) 
                        return;
                    filename = _files[_index++];
                }
                //complex work
                Console.WriteLine("Thread[{0}] {1}", Thread.CurrentThread.ManagedThreadId, filename);
                Thread.Sleep(200);
            }
        }
    }
      

  9.   

    按照这个代码,index不需要lock,整段代码都不需要lock。临界资源是lstPath,要锁也是锁对它的插入删除操作,代码中无对此操作,也不需要锁,index在不同线程之间也只有自增,自增操作对其他线程也无影响,
    按理说代码不需要加锁,请检查其他地方。