多线程从数据库二进制字段转成文件
旧系统的文件是以二进制保存在数据库字段中。
做系统切换时要把这些文件转换成文件
用到委托的多线程,这个以前也写过,这次写的时候又查了好久,
放在这标记一下。
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.IO; 10 using System.Threading; 11 12 namespace LZDataExport 13 { 14 public partial class CreateFile : Form 15 { 16 private DataTable dtLZ_KJ_CollectFile = null; 17 DbHelperSQL LZdbHelper = null; 18 string CurrentPath = ""; 19 MyDeleGateBytesToFile[] myDeleGates = null; 20 IAsyncResult[] results = null; 21 DateTime dtS = DateTime.Now; 22 int ThreadNum = 10; 23 int CompleteNum = 10; 24 private Object thisLock = new Object(); 25 private DataTable dtAllFsFileId = null; 26 public CreateFile() 27 { 28 InitializeComponent(); 29 //不设置的话线程回调时会提示: 线程间操作无效: 从不是创建控件的线程访问它。 30 Control.CheckForIllegalCrossThreadCalls = false; 31 } 32 33 private void Start_Click(object sender, EventArgs e) 34 { 35 Start.Text = "处理中。。"; 36 Start.Enabled = false; 37 dtAllFsFileId = new DbHelperSQL("JHDB_KJ").Query("select * from CollectFile_KJ").Tables[0]; 38 //理正数据库 39 LZdbHelper = new DbHelperSQL("LZDB"); 40 //当前路径 41 CurrentPath = Application.StartupPath + @"\KJ\Collect\"; 42 if (!Directory.Exists(CurrentPath)) 43 { 44 Directory.CreateDirectory(CurrentPath); 45 } 46 //获取所有附件记录表 47 dtLZ_KJ_CollectFile = LZdbHelper.Query("select top 100 Id,FK_Value,FIleName,FileExt,FileSize from FC_InfoAttach").Tables[0]; 48 dtS = DateTime.Now; 49 TimeLog.AppendText("开始:" + dtS.ToString("yyyy-MM-dd HH:mm:ss:ff") + "\r"); 50 myDeleGates = new MyDeleGateBytesToFile[ThreadNum]; 51 results = new IAsyncResult[ThreadNum]; 52 TimeLog.AppendText("总条数:" + dtLZ_KJ_CollectFile.Rows.Count.ToString() + "\r"); 53 int length = dtLZ_KJ_CollectFile.Rows.Count / ThreadNum; 54 for (int i = 0; i < ThreadNum; i++) 55 { 56 myDeleGates[i] = new MyDeleGateBytesToFile(BytesToFile); 57 int startNum = i * length; 58 int endNum = 0; 59 if (i == ThreadNum - 1) 60 { 61 endNum = dtLZ_KJ_CollectFile.Rows.Count; 62 } 63 else 64 { 65 endNum = (i + 1) * length; 66 } 67 AsyncCallback acb = new AsyncCallback(CallBackMethod); 68 //i会加到results[i].AsyncState 在回调时用到 69 results[i] = myDeleGates[i].BeginInvoke(startNum, endNum, acb, i); 70 TimeLog.AppendText("线程[" + i.ToString() + "]记录起止数:" + startNum.ToString() + "-" + endNum.ToString() + "\r"); 71 } 72 } 73 74 /// <summary> 75 /// 异步回调方法 76 /// </summary> 77 /// <param name="ar">开始异步时参数</param> 78 private void CallBackMethod(IAsyncResult ar) 79 { 80 //不加锁的话 同时返回就会出错。 81 lock (thisLock) 82 { 83 int i = (int)ar.AsyncState; 84 DateTime dtE = DateTime.Now; 85 TimeLog.AppendText("线程[" + i.ToString() + "]结束于:" + dtE.ToString("yyyy-MM-dd HH:mm:ss:ff") + "\r"); 86 TimeSpan tsS = new TimeSpan(dtS.Ticks); 87 TimeSpan tsE = new TimeSpan(dtE.Ticks); 88 TimeSpan teR = tsE.Subtract(tsS); 89 TimeLog.AppendText("用了:" + teR.TotalMilliseconds + "\r"); 90 LogTxt.AppendText(myDeleGates[i].EndInvoke(results[i]).ToString());//myDeleGates[i].EndInvoke(ar).ToString() 也可以 91 CompleteNum = CompleteNum - 1; 92 if (CompleteNum == 0) 93 { 94 MessageBox.Show("导入完成"); 95 } 96 } 97 } 98 99 100 /// <summary> 101 /// 二进制转成文件 跟定义的委托相同的签名 102 /// </summary> 103 /// <param name="StartNum">开始数</param> 104 /// <param name="EndNum">结束数</param> 105 /// <returns>StringBuilder</returns> 106 private StringBuilder BytesToFile(int StartNum, int EndNum) 107 { 108 StringBuilder sb = new StringBuilder(); 109 for (int i = StartNum; i < EndNum; i++) 110 { 111 DataRow dr = dtLZ_KJ_CollectFile.Rows[i]; 112 string FileName = CommandFunction.ObjectToStr(dtAllFsFileId.Select("LZFC_InfoAttach_Id='" + CommandFunction.ObjectToStr(dr["Id"]) + "'")[0]["FsFileId"]) + "_" + CommandFunction.ObjectToStr(dr["FIleName"]) + "." + CommandFunction.ObjectToStr(dr["FileExt"]); 113 //CommandFunction.ObjectToStr(dr["Id"]) + "_" + CommandFunction.ObjectToStr(dr["FIleName"]) + "." + CommandFunction.ObjectToStr(dr["FileExt"]); 114 string FullFilePath = ""; 115 FullFilePath = CurrentPath + FileName; 116 if (File.Exists(FullFilePath)) 117 { 118 sb.Append("[" + FileName + "]已经创建过\r"); 119 } 120 else 121 { 122 object FileData = LZdbHelper.GetSingle("select FileData from FC_InfoAttach where Id='" + dr["Id"].ToString() + "'"); 123 Byte[] Files = (Byte[])FileData; 124 BinaryWriter bw = new BinaryWriter(File.Open(FullFilePath, FileMode.OpenOrCreate)); 125 bw.Write(Files); 126 bw.Close(); 127 sb.Append("创建文件[" + FileName + "]成功\r"); 128 } 129 } 130 return sb; 131 132 } 133 134 //定义一个委托 135 private delegate StringBuilder MyDeleGateBytesToFile(int StartNum, int EndNum); 136 137 138 } 139 }
其中
1 object FileData = LZdbHelper.GetSingle("select FileData from FC_InfoAttach where Id='" + dr["Id"].ToString() + "'");
去数据库取二进制数据时,如果该文件很大,程序会提示 数据库操作超时。
因此在GetSingle方法里面设置了一下超时时间
View Code
1 /// <summary> 2 /// 执行一条计算查询结果语句,返回查询结果(object)。 3 /// </summary> 4 /// <param name="SQLString">计算查询结果语句</param> 5 /// <returns>查询结果(object)</returns> 6 public object GetSingle(string SQLString) 7 { 8 using (SqlConnection connection = new SqlConnection(connectionString)) 9 { 10 using (SqlCommand cmd = new SqlCommand(SQLString, connection)) 11 { 12 try 13 { 14 connection.Open(); 15 //设置取数据时的超时时间 16 cmd.CommandTimeout = 0; 17 object obj = cmd.ExecuteScalar(); 18 if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value))) 19 { 20 return null; 21 } 22 else 23 { 24 return obj; 25 } 26 } 27 catch (System.Data.SqlClient.SqlException e) 28 { 29 connection.Close(); 30 throw e; 31 } 32 } 33 } 34 }
posted on 2012-07-20 12:01 thegavincheng 阅读(258) 评论(0) 编辑 收藏 举报