/* by josh */

2014年10月8日 星期三

[MSQL] 釋放MSSQL Server Cache (緩衝集區裡沒有足夠的可用記憶體)

當出現"緩衝集區裡沒有足夠的可用記憶體"此項錯誤時,可嘗試使用以下指令釋放快取記憶體;或是於程式中固定一段時間執行此三個Query

操作指令(適用2005,2008):
DBCC FREESYSTEMCACHE('all')
DBCC FREESESSIONCACHE
DBCC FREEPROCCACHE WITH NO_INFOMSGS

2014年9月22日 星期一

[WCF] 建立net.tcp之WCF服務

以下示範如何建立一個使用net.tcp協定的WCF server
其中合約定義在IFileRepositoryService.cs
而合約內容實作在FileRepositoryService.cs


步驟1.設定服務內容(於App.config中點選右鍵->編輯WCF組態)


  • 設定服務的名稱及服務所使用的行為名稱
  • 在主機中加入net.tcp的服務位址
    



  • 新增端點並將端點類型設為netTcpBinding,另外需指定合約名稱
        
步驟2.新增一個類型為netTCPBinding的繫結(Binding),並設定繫結各項參數


步驟3.於[進階].[服務行為]中新增一個服務行為(serviceBehavior);且因為使用net.tcp的關係,此處必須新增一個serviceMetadata用來給SvcUtil.exe產生Proxy

  • serviceMetada中必須將HttpGetEnabled改為True;並且於HttpGetUrl中指定SvcUtil.exe去找尋服務的位址,此處不可與WCF net.tcp 服務使用同一個port



步驟4.程式中撰寫開啟服務的程式碼

 ServiceHost host;
 FileRepositoryService service;
 service = new FileRepositoryService();
 host = new ServiceHost(typeof(FileRepositoryService));
            
            
 host.Faulted += new EventHandler(Host_Faulted) 
 try
 {
    host.Open();
 }

其中ServiceHost位於System.ServiceModel命名空間中

程式執行後便可在SvcUtil中利用serviceMetadata中的服務位址去產生Proxy檔案及client的.config檔案

之後便可於Client端程式中加入此cs檔案並且利用此class新增wcf物件,而Client端的.config則使用output.config中的內容即可

2014年7月14日 星期一

[C#] 多執行緒互斥存取

使用多執行緒執設計的程式有可時會面臨到同一時間不同執行緒會存取同一檔案的情況,此時.NET會跳出由於另一個處理序正在使用檔案…”的例外。

若要避免此情況可使用C#的關鍵字”lock”;在lock區塊中的程式碼被某一個執行緒A占用時,若有其他執行緒B要執行,則必須等到執行緒A離開此區塊後,執行緒B才可進入。


For example
假設有一個Backgroundworker不斷寫入log如下圖:


void BackGroundWorker_writeLog(object sender,DoWorkEventArgs e)
{
 while (true)
 {
               lock (thisLock)
               {
                    objSystemEventLogShow.Show("背景執行緒   "+counter, false);
                    counter++;
               }
 }
}

主執行緒中另一個timer也會寫入log,如下:

private void timer1_Tick(object sender, EventArgs e)
        {
            lock (thisLock)
            {
                objSystemEventLogShow.Show("主執行緒   " + counter, true);
                counter = 1;
            }
        }

因為backgroundworker所產生的執行緒不斷地在寫log,若於backgroundworker正在寫入時,主執行緒timer正好被觸發且要寫入同一個檔案,此時便會產生例外造成程式終止。

為了避免此情況,可在寫log時的取塊中可以加入lock關鍵字;而lock()中的參數則可以想像成是一個mutex,執行緒需取得存取權才能進入函式中,函式執行完畢則釋放存取權。


所以,號誌應該被宣告為全域變數,且最好是靜態的(static)。此例中我在class開頭便做宣告,如下圖:


需要注意的是,Lock的位置必須放對,以上面的例子而言,如果將lock放在while(true)的外面,while迴圈不斷地執行,換句話說backgroundworker並不可能釋放log的資源,如此主執行緒timer將永遠等不到資源可以執行,如此便造成執行緒飢餓(starvation)。如下:

void BackGroundWorker_writeLog(object sender,DoWorkEventArgs e)
        {
            lock (thisLock)
            {
                while (true)
                {
                    objSystemEventLogShow.Show("背景執行緒   " + counter, false);
                    counter++;

                }
            }
        }

2014年3月26日 星期三

[C#] .NET Compact Framework 3.5之WCF 使用說明

微軟已在 .net compact framework 3.5版中加入了WCF client的功能(但並未支援WCF server);
要在.net compact framework上使用wcf service必須用到Power Toys for .NET Compact Framework 3.5中的ServiceModel Metadata Tool for the .NET Compact Framework (NetCFSvcUtil)程式來產生Proxies藉以呼叫WCF service。
注意:若你是使用Windows 7以上的OS開發,務必下載支援windows 7的NetCFSvcUtil,否則無法正確產生proxies

以下說明如何建立service及client,

Server端:
Step 1: 新增合約IGreetingService.cs,此例之合約名稱為IGreetingService

namespace WcfDemoService
{
 // 注意: 若變更此處的介面名稱 "IGreetingService",也必須更新 App.config 中 "IGreetingService" 的參考。

    [ServiceContract]
    public interface IGreetingService
    {
        [OperationContract]
        string DoWork();
              
    }
}

Step 2:實作合約內容GreetingService.cs


namespace WcfDemoService
{
    // 注意: 若變更此處的類別名稱 "GreetingService",也必須更新 App.config 中 "GreetingService" 的參考。
    public class GreetingService : IGreetingService
    {
        public string DoWork()
        {
            return "This is return string2";
        }
      
    }
}
Step 3: 在主程式中撰寫開啟服務的程式碼
 class Program
 {
        static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(GreetingService));
            try
            {
                host.Open();
                Console.WriteLine("Server Opened !");
                Console.Read();
            }
            finally
            {
                if (host.State == CommunicationState.Faulted)
                    host.Abort();
                else
                    host.Close();
            }
        }
 }
Step 4: 建立App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="WcfDemoService.GreetingServiceBehavior">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service behaviorConfiguration="WcfDemoService.GreetingServiceBehavior"
                name="WcfDemoService.GreetingService">
                <endpoint address="GreetingService" binding="basicHttpBinding" contract="WcfDemoService.IGreetingService" bindingConfiguration="basicHttpBindingConfiguration">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://192.168.0.103:8731"/>
                    </baseAddresses>
                </host>
            </service>
        </services>
      <bindings>
        <basicHttpBinding>
          <binding name="basicHttpBindingConfiguration" maxReceivedMessageSize="20971510">
            <readerQuotas maxStringContentLength="20971520" maxArrayLength="20971520"/>
         
          </binding>
        </basicHttpBinding>
      </bindings>
    </system.serviceModel>
</configuration>

Client端:
Step 1: 使用NetCFSvcUtil產生Proxy檔案,方法如下:
    a) 先執行host程式
    b)在cmd下cd到NetCFSvcUtil.exe的路徑下,輸入NetCFSvcUtil.exe http://host ip:host port/  按          下enter後會產生兩個檔案GreetingService.csCFClientBase.cs
        

Step 2:建立.net compact framework專案並匯入GreetingService.csCFClientBase.cs

Step 3: 在程式中撰寫呼叫wcf service的程式碼
private void btnGetStringByWCF_Click(object sender, EventArgs e)
{
System.ServiceModel.Channels.Binding binding = 
GreetingServiceClient.CreateDefaultBinding();
   string address = GreetingServiceClient.EndpointAddress.Uri.ToString();
   GreetingServiceClient m_proxy = 
new GreetingServiceClient(binding, new System.ServiceModel.EndpointAddress(address));
   
string GetString=m_proxy.DoWork();
  this.textBox1.Text = GetString;
}

2014年2月24日 星期一

[C#] 使用LinQ連接MS SQL Server發生error 26

當使用LinQ連接資料庫時發生Error 26時(如下圖)

此時請檢查Web,Config (App.Config) 檔案,並且確認Connection String為何,然後至 dbml的design.cs中找尋LinQ所使用的Connect string與Web.Config中相同
    1.) 確認.Config中設定了哪些DB連線及其名稱:

   2.)檢查dbml的design.cs中所使用的DB連線

    上圖LinQ所使用的connection string為ConnectionString3,在.Config中就必須有ConnectString3的設定且必須是可以連接到的DB

2014年1月8日 星期三