C#讀取Excel幾種方法的體會
(1) OleDb: 用這種方法讀取Excel速度還是非常的快的,但這種方式讀取資料的時候不太靈活,不過可以在 DataTable 中對資料進行一些刪減修改
這種方式將Excel作為一個數據源,直接用Sql語句獲取資料了。所以讀取之前要知道此次要讀取的Sheet(當然也可以用序號,類似dt.Row[0][0]。這樣倒是不需要知道Sheet)
?
if
(fileType == ".xls" )
connStr =
"Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source="
+ fileName + ";"
+ ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\"" ;
else
connStr =
"Provider=Microsoft.ACE.OLEDB.12.0;"
+ "Data Source="
+ fileName + ";"
+ ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\"" ;
OleDbConnection conn
new OleDbConnection(connStr);
DataTable dtSheetName = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,
new object [] {
null ,
null , null ,
"TABLE" });
|
以上是讀取Excel的Sheet名,xls和xlsx的連線字串也不一樣的,可以根據檔案的字尾來區別。這裡需要注意的一點,Excel裡面只有一個Sheet,但通過這種方式讀取Sheet可能會大於一個。原因已經有人在別的網站說過了,偷一下懶O(∩_∩)O,下面文段來自【cdwolfling】
【在使用過程中發現取出的Sheet和實際excel不一致, 會多出不少。目前總結後有兩種情況:
1. 取出的名稱中,包括了XL命名管理器中的名稱(參見XL2007的公式--命名管理器, 快捷鍵Crtl+F3);
對於第一點比較簡單, 刪除已有命名管理器中的內容即可;第二點處理起來比較麻煩, Filter刪除後這些名稱依然保留著,簡單的做法是新增sheet然後將原sheet Copy進去】
---------------------------------
但實際情況並不能為每個Excel做以上檢查,【cdwolfling】也給出了過濾的方案,當時還是有點問題,本來補充了一點。總之先看程式碼吧
for (int i = 0; i < dtSheetName.Rows.Count; i++)
{
?
SheetName = ( string )dtSheetName.Rows[i][ "TABLE_NAME" ];
if
(SheetName .Contains( "$" ) && !SheetName .Replace( "'" ,
"" ).EndsWith( "$" )) continue ; //過濾無效SheetName完畢....
|
da.SelectCommand = new OleDbCommand(String.Format(sql_F, tblName), conn);
DataSet dsItem = new DataSet();
da.Fill(dsItem, tblName);
}
|
因為讀取出來無效SheetName一般情況最後一個字元都不會是$。如果SheetName有一些特殊符號,讀取出來的SheetName會自動加上單引號,比如在Excel中將SheetName編輯成:MySheet(1),此時讀取出來的SheetName就為:'MySheet(1)$',所以判斷最後一個字元是不是$之前最好過濾一下單引號。
優點:讀取方式簡單、讀取速度快
缺點:除了讀取過程不太靈活之外,這種讀取方式還有個弊端就是,當Excel資料量很大時。會非常佔用記憶體,當記憶體不夠時會丟擲記憶體溢位的異常。
不過一般情況下還是非常不錯的
讀取Excel完整程式碼:
?
/// <summary>
/// 讀取Excel檔案到DataSet中
/// </summary>
/// <param name="filePath">檔案路徑</param>
/// <returns></returns>
public
static DataSet ToDataTable( string
filePath)
{
string
connStr = "" ;
string
fileType = System.IO.Path.GetExtension(fileName);
if
( string .IsNullOrEmpty(fileType))
return null ;
if
(fileType == ".xls" )
connStr =
"Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source="
+ filePath+ ";"
+ ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\"" ;
else
connStr =
"Provider=Microsoft.ACE.OLEDB.12.0;"
+ "Data Source="
+ filePath+ ";"
+ ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\"" ;
string
sql_F = "Select * FROM [{0}]" ;
OleDbConnection conn =
null ;
OleDbDataAdapter da =
null ;
DataTable dtSheetName=
null ;
DataSet ds =
new DataSet();
try
{
// 初始化連線,並開啟
conn =
new OleDbConnection(connStr);
conn.Open();
// 獲取資料來源的表定義元資料
string
SheetName = "" ;
dtSheetName= conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,
new object [] {
null ,
null , null ,
"TABLE" });
// 初始化介面卡
da =
new OleDbDataAdapter();
for
( int
i = 0; i < dtSheetName.Rows.Count; i++)
{
SheetName = ( string )dtSheetName.Rows[i][ "TABLE_NAME" ];
if
(SheetName .Contains( "$" ) && !SheetName .Replace( "'" ,
"" ).EndsWith( "$" ))
{
continue ;
}
da.SelectCommand =
new OleDbCommand(String.Format(sql_F, SheetName ), conn);
DataSet dsItem =
new DataSet();
da.Fill(dsItem, tblName);
ds.Tables.Add(dsItem.Tables[0].Copy());
}
}
catch
(Exception ex)
{
}
finally
{
// 關閉連線
if
(conn.State == ConnectionState.Open)
{
conn.Close();
da.Dispose();
conn.Dispose();
}
}
return
ds;
}
|
(2):Com元件的方式讀取Excel
這種方式需要先引用 Microsoft.Office.Interop.Excel 。首選說下這種方式的優缺點
優點:可以非常靈活的讀取Excel中的資料
缺點:如果是Web站點部署在IIS上時,還需要伺服器機子已安裝了Excel,有時候還需要為配置IIS許可權。最重要的一點因為是基於單元格方式讀取的,所以資料很慢(曾做過試驗,直接讀取千行、200多列的檔案,直接讀取耗時15分鐘。即使採用多執行緒分段讀取來提高CPU的利用率也需要8分鐘。PS:CPU I3)
需要讀取大檔案的的童鞋們慎重。。。
附上單執行緒和多執行緒讀取類:
?
public
class ExcelOptions
{
private
Stopwatch wath = new
Stopwatch();
/// <summary>
/// 使用COM讀取Excel
/// </summary>
/// <param name="excelFilePath">路徑</param>
/// <returns>DataTabel</returns>
public
System.Data.DataTable GetExcelData( string
excelFilePath)
{
Excel.Application app =
new Excel.Application();
Excel.Sheets sheets;
Excel.Workbook workbook =
null ;
object
oMissiong = System.Reflection.Missing.Value;
System.Data.DataTable dt =
new System.Data.DataTable();
wath.Start();
try
{
if
(app == null )
{
return
null ;
}
workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,
oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);
//將資料讀入到DataTable中——Start
sheets = workbook.Worksheets;
Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1); //讀取第一張表
if
(worksheet == null )
return
null ;
string
cellContent;
int
iRowCount = worksheet.UsedRange.Rows.Count;
int
iColCount = worksheet.UsedRange.Columns.Count;
Excel.Range range;
//負責列頭Start
DataColumn dc;
int
ColumnID = 1;
range = (Excel.Range)worksheet.Cells[1, 1];
while
(range.Text.ToString().Trim() != "" )
{
dc =
new DataColumn();
dc.DataType = System.Type.GetType( "System.String" );
dc.ColumnName = range.Text.ToString().Trim();
dt.Columns.Add(dc);
range = (Excel.Range)worksheet.Cells[1, ++ColumnID];
}
//End
for
( int
iRow = 2; iRow <= iRowCount; iRow++)
{
DataRow dr = dt.NewRow();
for
( int
iCol = 1; iCol <= iColCount; iCol++)
{
range = (Excel.Range)worksheet.Cells[iRow, iCol];
cellContent = (range.Value2 ==
null ) ?
"" : range.Text.ToString();
//if (iRow == 1)
//{
// dt.Columns.Add(cellContent);
//}
//else
//{
dr[iCol - 1] = cellContent;
//}
}
//if (iRow != 1)
dt.Rows.Add(dr);
}
wath.Stop();
TimeSpan ts = wath.Elapsed;
//將資料讀入到DataTable中——End
return
dt;
}
catch
{
return
null ;
}
finally
{
workbook.Close( false , oMissiong, oMissiong);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
workbook =
null ;
app.Workbooks.Close();
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app =
null ;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
/// <summary>
/// 使用COM,多執行緒讀取Excel(1 主執行緒、4 副執行緒)
/// </summary>
/// <param name="excelFilePath">路徑</param>
/// <returns>DataTabel</returns>
public
System.Data.DataTable ThreadReadExcel( string
excelFilePath)
{
Excel.Application app =
new Excel.Application();
Excel.Sheets sheets =
null ;
Excel.Workbook workbook =
null ;
object
oMissiong = System.Reflection.Missing.Value;
System.Data.DataTable dt =
new System.Data.DataTable();
wath.Start();
try
{
if
(app == null )
{
return
null ;
}
workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,
oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);
//將資料讀入到DataTable中——Start
sheets = workbook.Worksheets;
Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1); //讀取第一張表
if
(worksheet == null )
return
null ;
string
cellContent;
int
iRowCount = worksheet.UsedRange.Rows.Count;
int
iColCount = worksheet.UsedRange.Columns.Count;
Excel.Range range;
//負責列頭Start
DataColumn dc;
int
ColumnID = 1;
range = (Excel.Range)worksheet.Cells[1, 1];
//while (range.Text.ToString().Trim() != "")
while
(iColCount >= ColumnID)
{
dc =
new DataColumn();
dc.DataType = System.Type.GetType( "System.String" );
string
strNewColumnName = range.Text.ToString().Trim();
if
(strNewColumnName.Length == 0) strNewColumnName =
"_1" ;
//判斷列名是否重複
for
( int
i = 1; i < ColumnID; i++)
{
if
(dt.Columns[i - 1].ColumnName == strNewColumnName)
strNewColumnName = strNewColumnName +
"_1" ;
}
dc.ColumnName = strNewColumnName;
dt.Columns.Add(dc);
range = (Excel.Range)worksheet.Cells[1, ++ColumnID];
}
//End
//資料大於500條,使用多程序進行讀取資料
if
(iRowCount - 1 > 500)
{
//開始多執行緒讀取資料
//新建執行緒
int
b2 = (iRowCount - 1) / 10;
DataTable dt1 =
new DataTable( "dt1" );
dt1 = dt.Clone();
SheetOptions sheet1thread =
new SheetOptions(worksheet, iColCount, 2, b2 + 1, dt1);
Thread othread1 =
new Thread( new
ThreadStart(sheet1thread.SheetToDataTable));
othread1.Start();
//阻塞 1 毫秒,保證第一個讀取 dt1
Thread.Sleep(1);
DataTable dt2 =
new DataTable( "dt2" );
dt2 = dt.Clone();
SheetOptions sheet2thread =
new SheetOptions(worksheet, iColCount, b2 + 2, b2 * 2 + 1, dt2);
Thread othread2 =
new Thread( new
ThreadStart(sheet2thread.SheetToDataTable));
othread2.Start();
DataTable dt3 =
new DataTable( "dt3" );
dt3 = dt.Clone();
SheetOptions sheet3thread =
new SheetOptions(worksheet, iColCount, b2 * 2 + 2, b2 * 3 + 1, dt3);
Thread othread3 =
new Thread( new
ThreadStart(sheet3thread.SheetToDataTable));
othread3.Start();
DataTable dt4 =
new DataTable( "dt4" );
dt4 = dt.Clone();
SheetOptions sheet4thread =
new SheetOptions(worksheet, iColCount, b2 * 3 + 2, b2 * 4 + 1, dt4);
Thread othread4 =
new Thread( new
ThreadStart(sheet4thread.SheetToDataTable));
othread4.Start();
//主執行緒讀取剩餘資料
for
( int
iRow = b2 * 4 + 2; iRow <= iRowCount; iRow++)
{
DataRow dr = dt.NewRow();
for
( int
iCol = 1; iCol <= iColCount; iCol++)
{
range = (Excel.Range)worksheet.Cells[iRow, iCol];
cellContent = (range.Value2 ==
null ) ?
"" : range.Text.ToString();
dr[iCol - 1] = cellContent;
}
dt.Rows.Add(dr);
}
othread1.Join();
othread2.Join();
othread3.Join();
othread4.Join();
//將多個執行緒讀取出來的資料追加至 dt1 後面
foreach
(DataRow dr in
dt.Rows)
dt1.Rows.Add(dr.ItemArray);
dt.Clear();
dt.Dispose();
foreach
(DataRow dr in
dt2.Rows)
dt1.Rows.Add(dr.ItemArray);
dt2.Clear();
dt2.Dispose();
foreach
(DataRow dr in
dt3.Rows)
dt1.Rows.Add(dr.ItemArray);
dt3.Clear();
dt3.Dispose();
foreach
(DataRow dr in
dt4.Rows)
dt1.Rows.Add(dr.ItemArray);
dt4.Clear();
dt4.Dispose();
return
dt1;
}
else
{
for
( int
iRow = 2; iRow <= iRowCount; iRow++)
{
DataRow dr = dt.NewRow();
for
( int
iCol = 1; iCol <= iColCount; iCol++)
{
range = (Excel.Range)worksheet.Cells[iRow, iCol];
cellContent = (range.Value2 ==
null ) ?
"" : range.Text.ToString();
dr[iCol - 1] = cellContent;
}
dt.Rows.Add(dr);
}
}
wath.Stop();
TimeSpan ts = wath.Elapsed;
//將資料讀入到DataTable中——End
return
dt;
}
catch
{
return
null ;
}
finally
{
workbook.Close( false , oMissiong, oMissiong);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);
workbook =
null ;
app.Workbooks.Close();
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app =
null ;
GC.Collect();
GC.WaitForPendingFinalizers();
/*
object objmissing = System.Reflection.Missing.Value;
Excel.ApplicationClass application = new ApplicationClass();
Excel.Workbook book = application.Workbooks.Add(objmissing);
Excel.Worksheet sheet = (Excel.Worksheet)book.Worksheets.Add(objmissing,objmissing,objmissing,objmissing);
//操作過程 ^&%&×&……&%&&……
//釋放
sheet.SaveAs(path,objmissing,objmissing,objmissing,objmissing,objmissing,objmissing,objmissing,objmissing);
System.Runtime.InteropServices.Marshal.ReleaseComObject((object)sheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject((object)book);
application.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject((object)application);
System.GC.Collect();
*/
}
}
/// <summary>
/// 刪除Excel行
/// </summary>
/// <param name="excelFilePath">Excel路徑</param>
/// <param name="rowStart">開始行</param>
/// <param name="rowEnd">結束行</param>
/// <param name="designationRow">指定行</param>
/// <returns></returns>
public
string DeleteRows( string
excelFilePath, int
rowStart, int
rowEnd, int
designationRow)
{
string
result = "" ;
Excel.Application app =
new Excel.Application();
Excel.Sheets sheets;
Excel.Workbook workbook =
null ;
object
oMissiong = System.Reflection.Missing.Value;
try
{
if
(app == null )
{
return
"分段讀取Excel失敗" ;
}
workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,
oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);
sheets = workbook.Worksheets;
Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1); //讀取第一張表
if
(worksheet == null )
return
result;
Excel.Range range;
//先刪除指定行,一般為列描述
if
(designationRow != -1)
{
range = (Excel.Range)worksheet.Rows[designationRow, oMissiong];
range.Delete(Excel.XlDeleteShiftDirection.xlShiftUp);
}
Stopwatch sw =
new Stopwatch();
sw.Start();
int
i = rowStart;
for
( int
iRow = rowStart; iRow <= rowEnd; iRow++, i++)
{
range = (Excel.Range)worksheet.Rows[rowStart, oMissiong];
range.Delete(Excel.XlDeleteShiftDirection.xlShiftUp);
}
sw.Stop();
TimeSpan ts = sw.Elapsed;
workbook.Save();
//將資料讀入到DataTable中——End
return
result;
}
catch
{
return
"分段讀取Excel失敗" ;
}
finally
{
workbook.Close( false , oMissiong, oMissiong);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
workbook =
null ;
app.Workbooks.Close();
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app =
null ;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
public
void ToExcelSheet(DataSet ds,
string fileName)
{
Excel.Application appExcel =
new Excel.Application();
Excel.Workbook workbookData =
null ;
Excel.Worksheet worksheetData;
Excel.Range range;
try
{
workbookData = appExcel.Workbooks.Add(System.Reflection.Missing.Value);
appExcel.DisplayAlerts =
false ; //不顯示警告
//xlApp.Visible = true;//excel是否可見
//
//for (int i = workbookData.Worksheets.Count; i > 0; i--)
//{
// Microsoft.Office.Interop.Excel.Worksheet oWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbookData.Worksheets.get_Item(i);
// oWorksheet.Select();
// oWorksheet.Delete();
//}
for
( int
k = 0; k < ds.Tables.Count; k++)
{
worksheetData = (Excel.Worksheet)workbookData.Worksheets.Add(System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value,
System.Reflection.Missing.Value);
// testnum--;
if
(ds.Tables[k] != null )
{
相關推薦C#讀取Excel幾種方法的體會(1) OleDb: 用這種方法讀取Excel速度還是非常的快的,但這種方式讀取資料的時候不太靈活,不過可以在 DataTable 中對資料進行一些刪減修改 這種方式將Excel作為一個數據源,直接用Sql語句獲取資料了。所以讀取之前要知道此次要讀取的Sheet(當然也可以用序號,類似dt.Row[0] C#讀取Excel三種方式及比較1、OleDb方式 優點:把excel檔案當做一個數據源,利用sql來進行資料的讀取操作 缺點:不能讀取到某一個單元格 注:這個方法我沒有進行過實驗。故具體程式碼無法展示給大家 2、COM元件(即新增Microsoft.Office.Interop.Excel引用) 優點: Linux Ubuntu 下編譯Opencv c++專案的幾種方法Table of Contents 4.瞭解 1.使用g++命令列 pkg-config引數方法 新建一個cpp檔案:main.cpp,功能是輸入一幅影象檔案的路徑並顯示該影象: #include<opencv2/opencv.hpp> C語言從stdin讀取一行字串的幾種方法C語言從stdin讀取一行字串的幾種方法 gets gets函式的標頭檔案是<stdio.h>,原型如下: char *gets(char *s); gets從stdin中讀入一行內容到s指定的buffer中,當遇到換行符或EOF時讀取結束。讀取成功時,返 C#讀取路徑的幾種方法//獲取包含清單的已載入檔案的路徑或 UNC 位置。 public static string sApplicationPath = Assembly.GetExecutingAssembly ().Location; //result: X: C#讀取網絡卡地址的幾種方法轉自:http://www.cnblogs.com/diulela/archive/2012/04/07/2436111.html 以下是收集的幾種C#程式讀取MAC地址的方法,示例中是讀取所有網絡卡的MAC地址,如果僅需要讀取其中一個,稍作修改即可。 1 通過IPCo c#匯出Excel檔案的幾種方法using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Windows.Forms; using System.Re C++讀取配置檔案的幾種方法ini檔案的話讀取更方便點。C++中有寫ini檔案和讀ini檔案的函式(應該是VC環境提供的,標準C++沒有。)windows下就直接用函式讀取ini檔案 看的你配置檔案是什麼型別了,如果是xml檔案的話,可以用TinyXML解析器去解析,看這裡:http://www.c C#由DataSet匯出Excel檔案的幾種方法裡面的方法很多。 我只成功運行了下面四種(稍作修改並添加了一些總結),其他的方法,沒能成功執行。 不過感興趣的可以看一下,因為即使不能執行(不能執行的原因有很多,差一點都不行),其思路還是值得參考學習的。 //法一 private void ToExcel(Da C#多線程的幾種方法task start invoke 數組 erl method 並行計算 bsp nbsp 1、Theard2、TheardPool 線程池3、Task 在Theard上做了優化和改進,建議使用 .start();4、Task.Factory.Start(method) C#啟動外部程序以及等待外部程序關閉的幾種方法string C# main 無限 完成 nbsp text enable geb 1. 啟動外部程序,不等待其退出。 2. 啟動外部程序,等待其退出。 3. 啟動外部程序,無限等待其退出。 4. 啟動外部程序,通過事件監視其退出。 // using Sy C#中實現並發的幾種方法的性能測試返回 也不會 thead syn image 9.png 結果 次數 存在 原文地址:https://www.cnblogs.com/durow/p/4837746.html 0x00 起因 去年寫的一個程序因為需要在局域網發送消息支持一些命令和簡單數據的傳輸,所以寫了 c#除掉字符串最後一個字符幾種方法要去 參數 aaa style log int print mov www 有一數組;轉換為字符串後為 aaa|bbb|ccc|ddd|現要去掉最後一個|第一種方法:語句為:str1=aaa|bbb|ccc|ddd|str=str1.substring(0,lastinde C# 移動分分彩平臺搭建無標題欄窗體的幾種方法msdn sage pro 使用 protected wpa 方便 sdn cap 第一種,手工分分彩平臺搭建論壇:haozbbs.com Q1446595067 移動。 該方法根據鼠標位置實現窗體的移動。網上有很多相關的例子,這裏不再多講。 第二種,調用系統API原理:是 C#線程同步的幾種方法sso 代碼 services 讀寫 基於 star 代碼段 不能 命名 在網上也看過一些關於線程同步的文章,其實線程同步有好幾種方法,下面我就簡單的做一下歸納。 一、volatile關鍵字 volatile是最簡單的一種同步方法,當然簡單是要付出代價的。它 C#獲取當前路徑的幾種方法size start orm name uri path ant tom 當前 //1.獲取模塊的完整路徑。 string path1 = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileNam python os 設定讀取環境變數的幾種方法專案中的跳板機是用的使用者公私鑰鑑權的,登入跳板機需要使用的每個人的name,因此如果將封裝的MySQL或者Redis方法中傳入USERNAME作為引數的話,感覺有點傻。因此,考慮將名字寫入環境變數。 兩種方法: 1、使用os.environ.setdefault方法寫入(或者直接 求組合數C(n,m) % mod的幾種方法演算法一:乘法逆元,在m,n和mod比較小的情況下適用 乘法逆元:(a/b)% mod = a * b^(mod-2),mod為素數 #include<iostream> #include<cstdio> #include<cmath> 歸納一下:C#執行緒同步的幾種方法我們在程式設計的時候,有時會使用多執行緒來解決問題,比如你的程式需要在後臺處理一大堆資料,但還要使使用者介面處於可操作狀態;或者你的程式需要訪問一些外部資源如資料庫或網路檔案等。這些情況你都可以建立一個子執行緒去處理,然而,多執行緒不可避免地會帶來一個問題,就是執行緒同步的問題。如果這個問題處理不好,我們就 [轉]C/C++定義全域性變數/常量幾種方法的區別在討論全域性變數之前我們先要明白幾個基本的概念: 原文章地址:https://www.cnblogs.com/wanghetao/p/4492582.html 1. 編譯單元(模組): 在IDE開發工具大行其道的今天, |