2017年7月26日 星期三

GC.Collect如何影響垃圾回收(MS-Office轉檔運用)

  1. GC.Collect如何影響垃圾回收
根據垃圾回收的算法,對像在內存中是按代的方式存放的,通常情況下,當第0代沾滿分配的空間的時候(比如是256k),GC就會啟動去回收第0代對象,倖存的第0代對象會被放入第1代中去,第1代的對像要等到放滿了才會收集,因此,越是年輕的代越是被頻繁的收集,由於通常情況下GC只收集第0代對象,既保證了可回收較多的內存,又忽略了老一代的對象,從而加快了垃圾回收的速度,提升了性能。
因此當調用gc.collect的時候,相當於強制的對所有代,不管年輕還是老的都執行一次回收。由於垃圾回收器在回收的資源的時候,正在執行託管代碼的線程都會被掛起,具體的細節相當複雜,因為有的線程運行在不安全的點,CLR不能執行垃圾回收,因此CLR會採用線程劫持技術,即通過修改線程棧的方法,來做垃圾回收。這種複雜性使得性能降低。除非確定大量的舊對象死亡,才考慮調用這個方法。
所以,在一般情況下,盡量不要干預垃圾回收器工作,即盡量避免主動調用GC.Collect。
由於垃圾回收是異步的,CLR有一個專用的線程負責垃圾回收,因此,即使調用GC.Collect,也並不是實時的調用了Finalize,因此要保證確實調用了析構方法,可以使用語句GC.WaitForPendingFinalizers ()。
下面是一段代碼,通過註釋掉
GC.Collect();
GC.WaitForPendingFinalizers();
語句,看出端倪。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            AA aa1 = new AA("1");
            AA aa2 = new AA("2");
            AA aa3 = new AA("3");
            aa1 = null;
            aa2 = null;
            //GC.Collect();
            //GC.WaitForPendingFinalizers();
            var tmp = aa3;
        }
    }
    public class AA
    {
        public string id = "";
        public AA(string s)
        {
            id = s;
            Console.WriteLine("对象AA_" + s + "被创建了");
        }
        ~AA()
        {
            Console.WriteLine(id + " 析构函数被执行了");
        }
    }
}
當語句被註釋掉的時候,雖然aa1和aa2都設成了null,但是垃圾回收並不是馬上就把它們回收掉。對象可能都被放在第0代上,等進程結束的時候,由垃圾回收器一起回收。所以輸出如下,順序是321
e1373249592f420e854f3b035ddf3fd7
但是當取消註釋後,由於強制垃圾回收時,aa1對象和aa2對像都是null,因此就把它們回收掉了。順序就是213了。
b0b99d8b1eec4114b26e7fa195225f4b
注意,如果aa1和aa2不設成null,那麼強制回收時,並不認為這2個對象可以回收。因此還是會等到進程結束的時候才會回收。
  1. .NET FRAMEWORK 垃圾收集(GARBAGE COLLECTION)初了解
  1. C#实现MS-Office文档转Pdf(Word、Execel、PowerPoint、Visio、Project)

2017年7月13日 星期四

Canvas圖片彩色轉黑白

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"></meta>
<title>canvas</title>
<script type="text/javascript">
var cvs,ctx;


window.onload=function(){
cvs=document.getElementById("cvs");
ctx=cvs.getContext("2d");
/*
var img=new Image();
img.src="T.jpg";
img.onload=function(){
ctx.drawImage(this,0,0,cvs.width,cvs.height);
};
*/
};


function invertColor(){
var pixels= ctx.getImageData(0,0,cvs.width,cvs.height);
var data=pixels.data;
var ave;
for(var i=0;i<data.length;i+=4){
   ave=(data[i]+data[i+1]+data[i+2])/3;
data[i]=ave;
data[i+1]=ave;
data[i+2]=ave;
}
ctx.putImageData(pixels,0,0);
}
function loadfile(input){
var file=input.files[0];
var src=URL.createObjectURL(file);
var img=new Image();
img.src=src;
img.onload=function(){
ctx.drawImage(this,0,0,cvs.width,cvs.height);
}
}
function saveFile(){
var link=document.getElementById("download");
link.download="image.jpg";
link.href=cvs.toDataURL("Image/jpeg");
link.click();
}


</script>
</head>
<body >
<div>
<input type="file" onchange="loadfile(this);"></input>
<button onclick="saveFile();" >儲存檔案</button>
<a id="download"></a>
<button onclick="invertColor();">顏色變灰色</button>
</div>
<canvas id="cvs" width="800" height="600" style="border:1px solid #c3c3c3;"></canvas>


</body>

</html>

[C#] FileUpload 上傳檔案_過濾檔案及解析度


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace fileupload_test
{
   public partial class WebForm1 : System.Web.UI.Page
   {
       protected void Page_Load(object sender, EventArgs e)
       {

       }

       protected void Button1_Click(object sender, EventArgs e)
       {
           if (FU1.HasFile == false) return;

           // FU1.FileName 只有 "檔案名稱.附檔名",並沒有 Client 端的完整理路徑
           string filename = FU1.FileName;
           string extension = Path.GetExtension(filename).ToLowerInvariant();
           // 判斷是否為允許上傳的檔案附檔名
           List<string> allowedExtextsion = new List<string> { ".jpg", ".bmp", ".png" };
           if (allowedExtextsion.IndexOf(extension) == -1)
           {
               lblMessage.Text = "不允許該檔案上傳";
               return;
           }
           // 檢查 Server 上該資料夾是否存在,不存在就自動建立
           string serverDir = @"D:\FileUploadDemo";
           if (Directory.Exists(serverDir) == false) Directory.CreateDirectory(serverDir);


           //設定路徑

           string serverFilePath = Path.Combine(serverDir, filename);
           string fileNameOnly = Path.GetFileNameWithoutExtension(filename);

           //判斷解析度寬度小於140 px
           System.Drawing.Image myPic = System.Drawing.Image.FromFile(serverFilePath);
           if (myPic.Width < 140)
           {
               lblMessage.Text = "上傳失敗, 解析度寬度小於140 px!";
               myPic.Dispose(); //最後將物件釋放
               System.IO.File.Delete(serverFilePath); // 將檔案刪除
           }
           else
           {
               // 判斷 Server 上檔案名稱是否有重覆情況,有的話必須進行更名
               // 使用 Path.Combine 來集合路徑的優點
               //  以前發生過儲存 Table 內的是 \\ServerName\Dir(最後面沒有 \ 符號),
               //  直接跟 FileName 來進行結合,會變成 \\ServerName\DirFileName 的情況,
               //  資料夾路徑的最後面有沒有 \ 符號變成還需要判斷,但用 Path.Combine 來結合的話,
               //  資料夾路徑沒有 \ 符號,會自動補上,有的話,就直接結合
               int fileCount = 1;
               while (File.Exists(serverFilePath))
               {
                   // 重覆檔案的命名規則為 檔名_1、檔名_2 以此類推
                   filename = string.Concat(fileNameOnly, "_", fileCount, extension);
                   serverFilePath = Path.Combine(serverDir, filename);
                   fileCount++;
               }

               // 把檔案傳入指定的 Server 內路徑
               try
               {
                   FU1.SaveAs(serverFilePath);
                   lblMessage.Text = "上傳成功, 檔名為: " + filename + "圖片長寬為: " + myPic.Width + " × " + myPic.Height;
               }
               catch (Exception ex)
               {
                   lblMessage.Text = ex.Message;
               }
           }
       }
   }
}