使用多執行緒時,常會使用lock,防止不同執行緒對共享參數存取造成非預期的結果。
如:
設備開關控制,thread A要對設備送出open指令,
此時thread B啟動,要對設備送出close指令,
但thread B先執行完畢,最後設備仍然是open的。
因此,可使用lock對設備狀態進行鎖定,使執行緒同步化,
但使用lock可能因兩個thread互相等待造成Deadlock。
如:
worker thread異動資料後,觸發事件後,由UI thread取得該資料來顯示,
就造成thread互相等待而死結。
另外,lock也需針對個別變數使用不同的object,避免單核心CPU進行context switch後造成死結情形。
2017年2月7日 星期二
2016年12月12日 星期一
2016年11月16日 星期三
[.NET/Tool] Common.Logging與Log4Net的差異與使用
問題:
專案中會看到同時參考Common.Logging與Log4Net,Log4Net就可以輸出Log了,為何還需要Common.Logging?
說明:
專案是可以互相參考的,專案A使用Log4Net輸出log,專案B卻使用NLog,造成管理的不便,
此時使用Common.Logging可提供抽象,由Log4net等dll來實作這些方法,
可以整合Log4net或NLog等.NET常見的Log函式庫,讓專案間可以使用Common.Logging來當Interface。
使用NuGet加入Common.Logging後,using與建立log物件,如下圖:
在app.config加入Logging Configuration後(使用ConsoleOutLoggerFactoryAdapter),
即可輸出Console。
搭配Log4Net,使用NuGet加入Common.Logging.Log4Net1215(目前最新),NuGet就會自動加入對應的Log4Net版本1.2.15(package version為2.0.5),
一樣需設定Logging Configuration,即可輸出Console。
Logging Configuration需注意的是:
● factoryAdapter內的type屬性,最後的Common.Logging.Log4Net1215版本號需正確。
● factoryAdapter下的ConfigType屬性設為INLINE表示讀取專案app.config內設定,若沒設定該屬性,則須有外部設定檔。
輸出外部log,可使用RollingFileAppender。
附上Log4Net版本號與NuGet package version對應,如1.2.15對應NuGet 2.0.5。
參考資料:
http://netcommon.sourceforge.net/docs/2.1.0/reference/html/ch01.html
http://logging.apache.org/log4net/release/config-examples.html
https://cmatskas.com/extend-the-common-logging-api-with-log4net/
https://github.com/net-commons/common-logging/wiki/Common.Logging-Packaging-and-Versions
http://stackoverflow.com/questions/37171988/nuget-package-version-not-matching-reference-version
專案中會看到同時參考Common.Logging與Log4Net,Log4Net就可以輸出Log了,為何還需要Common.Logging?
說明:
專案是可以互相參考的,專案A使用Log4Net輸出log,專案B卻使用NLog,造成管理的不便,
此時使用Common.Logging可提供抽象,由Log4net等dll來實作這些方法,
可以整合Log4net或NLog等.NET常見的Log函式庫,讓專案間可以使用Common.Logging來當Interface。
使用NuGet加入Common.Logging後,using與建立log物件,如下圖:
在app.config加入Logging Configuration後(使用ConsoleOutLoggerFactoryAdapter),
即可輸出Console。
搭配Log4Net,使用NuGet加入Common.Logging.Log4Net1215(目前最新),NuGet就會自動加入對應的Log4Net版本1.2.15(package version為2.0.5),
一樣需設定Logging Configuration,即可輸出Console。
Logging Configuration需注意的是:
● factoryAdapter內的type屬性,最後的Common.Logging.Log4Net1215版本號需正確。
● factoryAdapter下的ConfigType屬性設為INLINE表示讀取專案app.config內設定,若沒設定該屬性,則須有外部設定檔。
輸出外部log,可使用RollingFileAppender。
附上Log4Net版本號與NuGet package version對應,如1.2.15對應NuGet 2.0.5。
參考資料:
http://netcommon.sourceforge.net/docs/2.1.0/reference/html/ch01.html
http://logging.apache.org/log4net/release/config-examples.html
https://cmatskas.com/extend-the-common-logging-api-with-log4net/
https://github.com/net-commons/common-logging/wiki/Common.Logging-Packaging-and-Versions
http://stackoverflow.com/questions/37171988/nuget-package-version-not-matching-reference-version
2016年10月23日 星期日
[C#] 使用Microsoft.Interop.Excel將Excel文件列印在同一頁(PageSetup)
說明:
將欄位較多的Excel文件自動列印在同一頁(將所有欄放入單一頁面)。
作法:
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Open(excelPath);
Excel.Worksheet worksheet = (Excel.Worksheet)workbook.ActiveSheet;
//Fit all columns on one page
excel.PrintCommunication = false;
Excel.PageSetup pageSetup = worksheet.PageSetup;
//FitToPagesTall property設為false,則以FitToPagesWide來縮放Worksheet
pageSetup.FitToPagesTall = false;
pageSetup.FitToPagesWide = 1;
excel.PrintCommunication = true;
workbook.Save();
worksheet.PrintOutEx();
workbook.Close();
excel.Quit();
參考來源:
https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.pagesetup.fittopagestall(v=office.15).aspx
http://stackoverflow.com/questions/25741049/how-to-set-fit-all-columns-on-one-page-in-print-tab
將欄位較多的Excel文件自動列印在同一頁(將所有欄放入單一頁面)。
作法:
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Open(excelPath);
Excel.Worksheet worksheet = (Excel.Worksheet)workbook.ActiveSheet;
//Fit all columns on one page
excel.PrintCommunication = false;
Excel.PageSetup pageSetup = worksheet.PageSetup;
//FitToPagesTall property設為false,則以FitToPagesWide來縮放Worksheet
pageSetup.FitToPagesTall = false;
pageSetup.FitToPagesWide = 1;
excel.PrintCommunication = true;
workbook.Save();
worksheet.PrintOutEx();
workbook.Close();
excel.Quit();
參考來源:
https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.pagesetup.fittopagestall(v=office.15).aspx
http://stackoverflow.com/questions/25741049/how-to-set-fit-all-columns-on-one-page-in-print-tab
2016年9月28日 星期三
[.NET] 使用HtmlAgilityPack與HAPXPathFinder擷取網頁上的資料
說明:
想擷取網頁上的資料,該怎麼做?
作法:
寫.NET的可以使用HtmlAgilityPack這個套件,可透過NuGet或自行下載後加入參考,
這裡以擷取統一發票中獎號碼為例(網址:http://invoice.etax.nat.gov.tw/)。
假設想擷取特別獎號碼,需要知道它的XPath,何謂XPath呢?
XPath(XML Path Languange),用來尋找XML檔案中的節點,詳細語法可參閱[1][2]。
一般而言,網頁的XPath大多像這樣:/html/body/div[1]/table[1]/tr[1]/td[1]。
找尋XPath主要有兩種方法:
● 檢視網頁原始碼來找尋XPath,或按F12開發者工具,再點選「選取元素」自行剖析XPath,Chrome可右鍵->Copy->Copy XPath。
● 使用HAPXPathFinder[3],曾自行剖析某網頁XPath,程式卻一直找不到該節點,使用HAPXPathFinder發現,該XPath沒有html tag...。因各瀏覽器產生的DOM有所差異,
使用HAPXPathFinder可以準確找出HtmlAgilityPack DOM的XPath。
打開HAPXPathFinder,在「Browser」tab輸入URL後,點選「DOM Tree」tab,
在TextBox輸入尋找內容->點選「Find」->點選右方Text區塊的搜尋結果
(->點選左方區塊的標示節點)->中間區塊即有節點的XPath(/#text[1]不需要)。如:
有了URL與XPath,就可以使用HtmlDocument.DocumentNode.SelectSingleNode方法的InnerText屬性來取得號碼了。 若找不到資料,可能是網頁編碼的問題,該網頁編碼使用UTF8。
參考資料:
[1] http://www.w3schools.com/xsl/xpath_syntax.asp
[2] https://msdn.microsoft.com/zh-tw/library/ms256086(v=vs.120).aspx
[3] https://hapxpathfinder.codeplex.com/
想擷取網頁上的資料,該怎麼做?
作法:
寫.NET的可以使用HtmlAgilityPack這個套件,可透過NuGet或自行下載後加入參考,
這裡以擷取統一發票中獎號碼為例(網址:http://invoice.etax.nat.gov.tw/)。
假設想擷取特別獎號碼,需要知道它的XPath,何謂XPath呢?
XPath(XML Path Languange),用來尋找XML檔案中的節點,詳細語法可參閱[1][2]。
一般而言,網頁的XPath大多像這樣:/html/body/div[1]/table[1]/tr[1]/td[1]。
找尋XPath主要有兩種方法:
● 檢視網頁原始碼來找尋XPath,或按F12開發者工具,再點選「選取元素」自行剖析XPath,Chrome可右鍵->Copy->Copy XPath。
● 使用HAPXPathFinder[3],曾自行剖析某網頁XPath,程式卻一直找不到該節點,使用HAPXPathFinder發現,該XPath沒有html tag...。因各瀏覽器產生的DOM有所差異,
使用HAPXPathFinder可以準確找出HtmlAgilityPack DOM的XPath。
打開HAPXPathFinder,在「Browser」tab輸入URL後,點選「DOM Tree」tab,
在TextBox輸入尋找內容->點選「Find」->點選右方Text區塊的搜尋結果
(->點選左方區塊的標示節點)->中間區塊即有節點的XPath(/#text[1]不需要)。如:
有了URL與XPath,就可以使用HtmlDocument.DocumentNode.SelectSingleNode方法的InnerText屬性來取得號碼了。 若找不到資料,可能是網頁編碼的問題,該網頁編碼使用UTF8。
參考資料:
[1] http://www.w3schools.com/xsl/xpath_syntax.asp
[2] https://msdn.microsoft.com/zh-tw/library/ms256086(v=vs.120).aspx
[3] https://hapxpathfinder.codeplex.com/
2016年8月21日 星期日
[.NET] 使用Sandcastle製作軟體help file的sample code
說明:
軟體開發完成後,需要有說明文件方便使用者查詢使用,
微軟有提供CHM(Compiled HTML)的說明檔格式,
使用Sandcastle與GhostDoc(professional版以上)都可產出CHM help file,
但如果還想要加入sample code的頁面,該如何做呢?
作法:
可使用Sandcastle Help File Builder(SHFB)這套免費工具,又是獨立的編譯器,使用上也較方便。
● 先下載SHFB(http://shfb.codeplex.com/)並安裝,安裝後執行Sandcastle Help File Builder GUI。
● 上方選單列->File->New Project->輸入專案名稱並存檔。
● 在右方Project Explorer中的Documentation Sources上右鍵,選擇Add Documentation Sources...,加入軟體專案編譯後的dll與XML,(專案XML需在專案屬性->建置->輸出區塊,勾選XML文件檔案)。
● 接著在專案名稱上右鍵->Add->New Item,加入Code Snippets與Content Layout,可更改檔名後存檔。
● 點開Code Snippets,將item的id改成需要的名稱,例:SampleCode#NewInstance, sampleCode tag中則是要顯示的程式碼,預設有C#與VB,<可用<、>用>取代。
● 點開Content Layout,點選主畫面左上角的Add a new topic as a sibling of the selected topic,選擇Standard Templates的Sample,填入檔名後Add。
● 點開上一步加入的Sample.aml,在section中的content tag中加上<codeReference>item id</codeReference>,例:
<section address="Section1">
<title>Create Instance</title>
<content>
<para>建立實體物件</para>
<codeReference>SampleCode#NewInstance</codeReference>
</content>
</section>
● 調整想要的Project Properties後,上方選單列->Documentation->Build Project,建置結束後,選單列->Documentation->View Help File即可。
參考資料:
http://www.codeproject.com/Articles/141766/Creating-documentation-for-a-NET-component-with-Sa
http://community.submain.com/blogs/tutorials/archive/2014/03/05/conceptual-content-adding-custom-content-to-api-documentation-created-with-ghostdoc.aspx
http://huan-lin.blogspot.com/2009/02/use-sandcastle-file-builder-to-create.html
http://www.codeproject.com/KB/XML/csharpcodedocumentation.aspx?msg=1679454
軟體開發完成後,需要有說明文件方便使用者查詢使用,
微軟有提供CHM(Compiled HTML)的說明檔格式,
使用Sandcastle與GhostDoc(professional版以上)都可產出CHM help file,
但如果還想要加入sample code的頁面,該如何做呢?
作法:
可使用Sandcastle Help File Builder(SHFB)這套免費工具,又是獨立的編譯器,使用上也較方便。
● 先下載SHFB(http://shfb.codeplex.com/)並安裝,安裝後執行Sandcastle Help File Builder GUI。
● 上方選單列->File->New Project->輸入專案名稱並存檔。
● 在右方Project Explorer中的Documentation Sources上右鍵,選擇Add Documentation Sources...,加入軟體專案編譯後的dll與XML,(專案XML需在專案屬性->建置->輸出區塊,勾選XML文件檔案)。
● 接著在專案名稱上右鍵->Add->New Item,加入Code Snippets與Content Layout,可更改檔名後存檔。
● 點開Code Snippets,將item的id改成需要的名稱,例:
● 點開Content Layout,點選主畫面左上角的Add a new topic as a sibling of the selected topic,選擇Standard Templates的Sample,填入檔名後Add。
● 點開上一步加入的Sample.aml,在section中的content tag中加上<codeReference>item id</codeReference>,例:
<section address="Section1">
<title>Create Instance</title>
<content>
<para>建立實體物件</para>
<codeReference>SampleCode#NewInstance</codeReference>
</content>
</section>
● 調整想要的Project Properties後,上方選單列->Documentation->Build Project,建置結束後,選單列->Documentation->View Help File即可。
參考資料:
http://www.codeproject.com/Articles/141766/Creating-documentation-for-a-NET-component-with-Sa
http://community.submain.com/blogs/tutorials/archive/2014/03/05/conceptual-content-adding-custom-content-to-api-documentation-created-with-ghostdoc.aspx
http://huan-lin.blogspot.com/2009/02/use-sandcastle-file-builder-to-create.html
http://www.codeproject.com/KB/XML/csharpcodedocumentation.aspx?msg=1679454
訂閱:
文章 (Atom)













