从数据库读出数据,每次100条,然后写进excel
在创建EXCEL时,我多线程,但是由于创建EXCEL文件时是需要时间的,所以线程之间需要同步知道正在创建哪个EXCEL文件,不能重名创建,这个线程的同步我该如何实现?
static void Main(string[] args)
        {
            CreateThreads();
        }
public static void CreateThreads()
        {
            Program pr = new Program();
            Thread[] ThreadtoExcel;
            ThreadStart toExcel = new ThreadStart(pr.CreateExcel);
            ThreadtoExcel = new Thread[C];//为线程申请资源,确定线程总数            
            for (int i = 1; i < C; i++)//开启指定数量的线程数            
            {
                ThreadtoExcel[i] = new Thread(toExcel);//指定线程起始设置
                ThreadtoExcel[i].Start();
            }
        }
public void CreateExcel()
        {
            for (int n = 1; n < 100; n++)
            {
                SqlConnection conn = new SqlConnection(@"Server=.;Initial Catalog=person;Uid=sa;Pwd=111111;");
                conn.Open();
                SqlCommand cmd = new SqlCommand(@"SELECT TOP 100 * FROM BASEINFO WHERE ID NOT IN (SELECT ID FROM UID)", conn);
                SqlDataAdapter ada = new SqlDataAdapter(cmd);
                DataSet ds = new DataSet();
                ada.Fill(ds);
                System.Data.DataTable t = ds.Tables[0];
                if (t == null) return;
                try
                {
                    Microsoft.Office.Interop.Excel.Application oExcel;
                    Microsoft.Office.Interop.Excel.Workbook oBook;
                    Object oMissing = System.Reflection.Missing.Value;
                    oExcel = new Microsoft.Office.Interop.Excel.Application();
                    oBook = oExcel.Workbooks.Add(oMissing);
                    for (int c = 0; c < t.Rows.Count; c++)
                    {
                        for (int i = 1; i < t.Columns.Count; i++)
                        {
                            string a = t.Rows[c][i].ToString();                            oExcel.Cells[c + 1, i] = t.Rows[c][i].ToString();
                        }
                        cmd = new SqlCommand(@"insert into uid(ID)values('" + Convert.ToInt32(t.Rows[c][0].ToString()) + "')", conn);
                        cmd.ExecuteNonQuery();
                    }
                    oBook.Saved = true;
                    oExcel.UserControl = false;
                    string Dir = "d:\\aaa\\";
                    string ExcelFile = n + "_Profile";
                    string FileName = Dir + ExcelFile + ".xls";
                       //这里该如何知道线程正在创建的n_ 文件呢?现在执行时,从1_开始创建,5个线程,会出现 
//create excel 1/xxx 
//create excel 2/xxx 
//create excel 2/xxx 
//create excel 2/xxx 
//create excel 2/xxx//然后是3 3 444 5 这种,请帮忙                        while (File.Exists(FileName))
                        {
                            n += 1;
                            FileName = n + "_profile" + ".xls";
                        }
                        string XLS = FileName;
                        oExcel.ActiveWorkbook.SaveCopyAs(XLS);
                    oExcel.Quit();
                    oExcel = null;
                    GC.Collect();
                    Console.WriteLine("Create Excel {0}/{1}", n, Count);
                }
                catch (Exception exp)
                {
                    Console.WriteLine(exp.ToString());
                    //Console.ReadLine();
                }
            }
            Console.WriteLine("Done");
            Console.ReadLine();
        }

解决方案 »

  1.   

    对,因为下一次产生随机数时需要在下次的循环,和N是一样的,线程间没有同步
    除非 DateTime.Now.Day.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString()
      

  2.   

    是用的Random.Next() 生成的随机数么?
      

  3.   

    是的,我现在用时间来做名称,但是又出现新的问题,在执行到
     cmd = new SqlCommand(@"insert into uid(ID)values('" + Convert.ToInt32(t.Rows[c][0].ToString()) + "')", conn);
                            cmd.ExecuteNonQuery();
    这里时,还没有执行完,下一个线程已经去读数据,这个插入操作是把已经转过的数据插到新表,在读数据时不读它们
      

  4.   


    这是另外一个问题了.
    uid表中要加入一个标记字段,举例,bit型的Converted
    在你执行
    insert into
    的时候,标记为 1
    SELECT TOP 100 
    的时候加上条件
     WHERE ID NOT IN (SELECT ID FROM UID WHERE Converted = 0)这样就不会循环读取了
      

  5.   


    这样做是一样的啊,我在取数据时取的是id不在uid表的,在插入数据时,因为不同步,还没插数据,另一个线程已经去读了,造成读的数据是一样的,增加个字段是没有任何意义的,因为在操作这个字段时,别的线程又去读了,还没操作完,数据又被读了,结果数据还是一样的
      

  6.   

    不一样,对数据库来说是原子操作
    我的意思是在表中加个状态字段
    无论哪个线程,在你读之后的事务里马上更新被读的这条的状态,
    这样别的线程读取的时候判断这个状态,非这个状态的才会被读走.例
    t_uid中
    uid,status
    1,未读select后update status字段
    1,已读其他线程的select 的条件where status ='未读'
    则不会造成重复读取