<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/&quot;AkcNR3ozfip7ImA9WxNUGUk.&quot;"><id>tag:blogger.com,1999:blog-18337532</id><updated>2009-11-11T21:01:36.486+07:00</updated><title type="text">Truong Hong Thi on .NET</title><subtitle type="html">Thoughts and ideas on .NET</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://thith.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://thith.blogspot.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><author><name>Truong Hong Thi</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>6</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/thith" type="application/atom+xml" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">thith</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsalloy.com/?rss=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://www.newsalloy.com/subrss3.gif">Subscribe with NewsAlloy</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://download.attensa.com/app/get_attensa.html?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://www.attensa.com/blogs/attensa/WindowsLiveWriter/BadgeredintoBadges_10C02/attensa_feed_button5.gif">Subscribe with Attensa for Outlook</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.flurry.com/pushRssFeed.do?r=fb&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://www.flurry.com/images/flurry_rss_logo2.gif">Subscribe with Flurry</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2Fthith" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;CUcDSH8zfyp7ImA9WBBWEkw.&quot;"><id>tag:blogger.com,1999:blog-18337532.post-814658589554612416</id><published>2006-12-04T13:09:00.000+07:00</published><updated>2006-12-04T13:17:59.187+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2006-12-04T13:17:59.187+07:00</app:edited><title>Enable the Registry Editor</title><content type="html">&lt;p&gt;Sometimes, my machine is infected by some virus. Almost all viruses change many registry entries and disable the Windows Registry Editor (Regedt32.exe and Regedit.exe) so that I could not change them back. Of course, that is not a problem if you have some other tool to edit the Windows Registry; but I don't have such tool. Creating a &lt;i&gt;.reg&lt;/i&gt; file and import into the registry often does not help because Windows could be configured to deny running registry editor in silent mode. Trying to enable the Windows registry editor by using Group Policy (gpedit.msc) might still no help, and even the Group Policy could be disabled. Plus, not everyone knows how to edit the &lt;i&gt;.reg&lt;/i&gt; file or using Group Policy. That is why I wrote a small C# tool to enable the registry editor. The source code of the tool is like this:&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.Win32;
&lt;span class="kwrd"&gt;string&lt;/span&gt; path = &lt;span class="str"&gt;@&amp;quot;Software\Microsoft\Windows\CurrentVersion\Policies\System&amp;quot;&lt;/span&gt;;
&lt;span class="kwrd"&gt;using&lt;/span&gt; (RegistryKey key = Registry.CurrentUser.OpenSubKey(path, &lt;span class="kwrd"&gt;true&lt;/span&gt;))
{
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (key != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
  {
    Object o = key.GetValue(&lt;span class="str"&gt;&amp;quot;DisableRegistryTools&amp;quot;&lt;/span&gt;);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (o != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
      key.DeleteValue(&lt;span class="str"&gt;&amp;quot;DisableRegistryTools&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
    }
  }
}&lt;/pre&gt;
&lt;p&gt;The snippet above deletes the &amp;quot;DisableRegistryTools&amp;quot;. Note that you achieve the same result by updating the value to 0, which is the default value if the entry is not there. &amp;quot;DisableRegistryTools&amp;quot; is a DWORD whose value could be one of the following:&lt;/p&gt;
&lt;table border="1" width="100%" style="border-collapse: collapse;" cellpadding="4"&gt;
  &lt;tr&gt;
    &lt;td&gt;&amp;nbsp;&amp;nbsp;0&amp;nbsp;&amp;nbsp;&lt;/td&gt;
    &lt;td&gt;Default. Registry Editor can be started either in interactive mode or in silent mode. &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&amp;nbsp;&amp;nbsp;1&amp;nbsp;&amp;nbsp;&lt;/td&gt;
    &lt;td&gt;Registry Editor can only be started in silent mode. You can still import an .reg file.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&amp;nbsp;&amp;nbsp;2&amp;nbsp;&amp;nbsp;&lt;/td&gt;
    &lt;td&gt;Registry Editor cannot be started at all.&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Some viruses also add &amp;quot;DisableRegistryTools&amp;quot; entry to &lt;i&gt;HKEY_USERS\.DEFAULT&lt;/i&gt;, so I should also delete it:&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; (RegistryKey key = Registry.Users.OpenSubKey(&lt;span class="str"&gt;@&amp;quot;.DEFAULT\&amp;quot;&lt;/span&gt; + path, &lt;span class="kwrd"&gt;true&lt;/span&gt;))
{
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (key != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
  {
    Object o = key.GetValue(&lt;span class="str"&gt;&amp;quot;DisableRegistryTools&amp;quot;&lt;/span&gt;);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (o != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
      key.DeleteValue(&lt;span class="str"&gt;&amp;quot;DisableRegistryTools&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
    }
  }
}&lt;/pre&gt;
&lt;p&gt;You may want to start the registry editor right after enabling it:&lt;/p&gt;
&lt;pre class="csharpcode"&gt;System.Diagnostics.Process.Start(&lt;span class="str"&gt;&amp;quot;regedit.exe&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;p&gt;Note that you should first kill every malware process or it will re-disable the tool very soon. Many viruses disable the Windows Task Manager and/or automatically restart the computer when you open it. In that case, you may need a third-party tool, like &lt;a href="http://www.sysinternals.com/Files/ProcessExplorerNt.zip"&gt;Process Explorer&lt;/a&gt;, to identify and kill malicious processes. However, I also included this functionality in my tool. Just drag a list box (lstProcess) and a button (btnKill) onto the form:&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Form1_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, System.EventArgs e)
{
  lstProcess.Items.AddRange(Process.GetProcesses());
}

&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnKill_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, System.EventArgs e)
{
  Process selectedProcess = lstProcess.SelectedItem &lt;span class="kwrd"&gt;as&lt;/span&gt; Process;
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (selectedProcess == &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;return&lt;/span&gt;; &lt;span class="rem"&gt;// no item selected&lt;/span&gt;

  &lt;span class="kwrd"&gt;string&lt;/span&gt; exePath = selectedProcess.MainModule.FileName;
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (DialogResult.OK ==
    MessageBox.Show(&lt;span class="str"&gt;&amp;quot;Kill: &amp;quot;&lt;/span&gt; + exePath, &lt;span class="str"&gt;&amp;quot;Confirm kill&amp;quot;&lt;/span&gt;, MessageBoxButtons.OKCancel))
  {
    selectedProcess.Kill();
  }
}&lt;/pre&gt;
&lt;p&gt;After starting registry editor, you should check all programs that automatically run when Windows starts and delete malicious entries and their physical files (some versions of Windows include a good tool for this purpose (msconfig.exe), but some malware might still escape so you had better check the registry - see &lt;a href="http://support.microsoft.com/kb/179365"&gt;Run and RunOnce Registry Keys&lt;/a&gt; to know where to check). Then check and delete malicious scheduled tasks. Also check Windows services (run services.msc). Following are some other registry entries that you should check:&lt;/p&gt;
&lt;p&gt;&lt;small&gt;HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell&lt;br&gt;
HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System\DisableTaskMgr&lt;br&gt;
HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System\DisableCMD&lt;br&gt;
HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoFolderOptions&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Believe it or not, I have cleaned many viruses on my PC just with the help of my tool and the Windows' search functionality to search for recently created files which are likely malware ones.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18337532-814658589554612416?l=thith.blogspot.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2DQlW9xR5WBOl6puAiGtCk7MY_k/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2DQlW9xR5WBOl6puAiGtCk7MY_k/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2DQlW9xR5WBOl6puAiGtCk7MY_k/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2DQlW9xR5WBOl6puAiGtCk7MY_k/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thith?a=4_-bFj6ctWY:GiRVcWTVBqk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thith?a=4_-bFj6ctWY:GiRVcWTVBqk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?i=4_-bFj6ctWY:GiRVcWTVBqk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://thith.blogspot.com/feeds/814658589554612416/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=18337532&amp;postID=814658589554612416" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/814658589554612416?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/814658589554612416?v=2" /><link rel="alternate" type="text/html" href="http://thith.blogspot.com/2006/12/enable-registry-editor.html" title="Enable the Registry Editor" /><author><name>Truong Hong Thi</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00479434843416697005" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;DkEGR3w5eCp7ImA9WBBQFUQ.&quot;"><id>tag:blogger.com,1999:blog-18337532.post-523588470354761605</id><published>2006-11-15T13:54:00.000+07:00</published><updated>2006-11-15T19:43:46.220+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2006-11-15T19:43:46.220+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Blogging" /><title>Format code snippets in blogs</title><content type="html">&lt;p&gt;When blogging, I frequently have to copy code and paste it to my post. It is nice if I have the snippet formatted like it is in Visual Studio. In the past, if the snippet is short, I would put it in &lt;i&gt;&amp;lt;pre&amp;gt;&lt;/i&gt; tag and manually colorize keywords, comments and strings. If the snippet was long, I would copy it from Visual Studio and paste into Word then copy to my post.&lt;/p&gt;&lt;p&gt;Recently, a friend of mine told me about &lt;a href="http://www.manoli.net/csharpformat/"&gt;http://www.manoli.net/csharpformat&lt;/a&gt; which can do the job for me. Despite the page's URL, it could format C#, VB, JavaScript, HTML, XML, ASPX, and MSH. The nice thing about code formatted by that page is that it makes use of CSS so I can paste the CSS stuff into my Blogger's template. Imagine some day I want to change the color of the keywords, just update the CSS and it will apply to all snippets in the blog. The page also let me download the source code, so I wrote a winform application myself using that DLL and added support for some other languages, like Java. It works nice, although sometimes it hangs with bad input :). I also changed the CSS a little to make the formatted code look more like that inside Visual Studio. I'll re-format every snippet in my blog.&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; HelloWorld
{
    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program
    {
        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
        {
            Console.WriteLine(&lt;span class="str"&gt;&amp;quot;Hello World!&amp;quot;&lt;/span&gt;);
        }
    }
}&lt;/pre&gt;&lt;p&gt;The HTML source the tool generates (the HTML source itself is also colorized by the tool):&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;pre&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;csharpcode&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;using&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; System;

&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;namespace&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; HelloWorld
{
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;class&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; Program
    {
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;static&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;void&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Main(&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;string&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;[] args)
        {
            Console.WriteLine(&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;str&amp;quot;&amp;gt;&lt;/span&gt;&amp;quot;Hello World!&amp;quot;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;);
        }
    }
}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;pre&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Look nice, doesn't it?&lt;/p&gt;&lt;p&gt;There was one problem: in some browsers, the &lt;em&gt;&amp;lt;pre&amp;gt;&lt;/em&gt; tag does not wrap. In many pages (like ones in this blog), long lines would go out of the border of its containing panel and there is no way to see the obscured parts. Fortunately, there is a way out: update CSS to make &lt;em&gt;&amp;lt;pre&amp;gt; &lt;/em&gt;wrap as described at &lt;a href="http://myy.helia.fi/~karte/pre-wrap-css3-mozilla-opera-ie.html"&gt;http://myy.helia.fi/~karte/pre-wrap-css3-mozilla-opera-ie.html&lt;/a&gt;. After I updated the Blogger template, everything was fine.&lt;/p&gt;&lt;pre class="csharpcode"&gt;.csharpcode, .csharpcode pre {
    font-size: small;
    color: black;
    font-family: Consolas, "Courier New", Courier, Monospace;
    background-color: #f4f4f4;
    white-space: pre-wrap;       /* css-3 */
    white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
    white-space: -pre-wrap;      /* Opera 4-6 */
    white-space: -o-pre-wrap;    /* Opera 7 */
    word-wrap: break-word;       /* Internet Explorer 5.5+ */
}&lt;/pre&gt;&lt;p&gt;Sorry the CSS code is not colorized as the tool does not support CSS yet.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18337532-523588470354761605?l=thith.blogspot.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/A715b8yge2CLiTXVVBzi8or88G4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/A715b8yge2CLiTXVVBzi8or88G4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/A715b8yge2CLiTXVVBzi8or88G4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/A715b8yge2CLiTXVVBzi8or88G4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thith?a=TIu8Wbq_qXE:OmhwD-_rerY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thith?a=TIu8Wbq_qXE:OmhwD-_rerY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?i=TIu8Wbq_qXE:OmhwD-_rerY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://thith.blogspot.com/feeds/523588470354761605/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=18337532&amp;postID=523588470354761605" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/523588470354761605?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/523588470354761605?v=2" /><link rel="alternate" type="text/html" href="http://thith.blogspot.com/2006/11/format-code-snippets-in-blogs.html" title="Format code snippets in blogs" /><author><name>Truong Hong Thi</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00479434843416697005" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total></entry><entry gd:etag="W/&quot;CkQCRHk-eSp7ImA9WBBQFUU.&quot;"><id>tag:blogger.com,1999:blog-18337532.post-499229115784988201</id><published>2006-10-27T17:38:00.000+07:00</published><updated>2006-11-15T15:46:05.751+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2006-11-15T15:46:05.751+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ideas" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Exception" /><title>What makes an API good</title><content type="html">&lt;p&gt;Today, once again, one of my colleagues called me to his desk and asked why  the following code did not work as expected:&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;pre class="csharpcode"&gt;Debug.WriteLine(&lt;span class="str"&gt;"Message received: {0}"&lt;/span&gt;, receivedMessage);&lt;/pre&gt;&lt;p&gt; &lt;/p&gt; &lt;p&gt;It should print out something like "Message received: Hello", right?&lt;/p&gt; &lt;p&gt;I've seen someone else have this problem before, and I myself did run into it.&lt;/p&gt; &lt;p&gt;- Look at the infotip. The first param is the message, and the second one is  its category.&lt;/p&gt; &lt;p&gt;- Uh oh, category. How could I miss that!&lt;/p&gt; &lt;p&gt;I know why. He, as well as me and many other developers, expect  Debug.WriteLine to work the same way as Console.WriteLine; so much that we do  not notice the infotip's contents. Because Console.WriteLine is too well-known, I consider  the signature of Debug.WriteLine bad design.&lt;/p&gt; &lt;p&gt;Good API is intuitive. The key to that is being consistent with well-known  and widely used patterns. It is ideal if developers could code without looking at  the documentation. Although computer is getting faster, it still takes some time  to load the documentation. That reduces productivity and tests the developer's  mentality. Thanks to good modern IDEs, we now less and less have to consult  documentation. The usual reason I still have to look at the doc is to check out  the &lt;i&gt;Exceptions&lt;/i&gt; section. Of course, sometimes I have to consult the other  information like thread safety, remarks, examples, etc. - but that is for more  complex API when looking at the documentation is necessary.&lt;/p&gt; &lt;p&gt;I always wish that the IDE should somehow let users view exception  information, at least for system types, in some form of intellisense dialog.  It could do this by parsing the XML comments. The pitfall of this is that it  might mislead the developer to trust that exception information which will  certainly cause troubles if the method is poorly XML documented (it might still  be documented well in some form else, but not XML comments). Exception  documentation is just a good practice, not a contract. Java has experimented  exception specification, with some benefits and some drawbacks. I am thinking of  some solutions, like ExceptionAttribute, but none of them really helps.&lt;/p&gt; &lt;p&gt;Nevertheless, a good API should expose as much useful information as possible,  in form of contracts, metadata (attributes), or at least standardized  comments/documentation. Consistent style, self-documented names, commonly-used  members/features emphasized. Good API + good IDE save developers' lives. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18337532-499229115784988201?l=thith.blogspot.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/B6DDOnZcp-ughZ7j1OdmWma2Qjs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/B6DDOnZcp-ughZ7j1OdmWma2Qjs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/B6DDOnZcp-ughZ7j1OdmWma2Qjs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/B6DDOnZcp-ughZ7j1OdmWma2Qjs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thith?a=WE-Gk51fvIg:O_i9BftzR1M:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thith?a=WE-Gk51fvIg:O_i9BftzR1M:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?i=WE-Gk51fvIg:O_i9BftzR1M:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://thith.blogspot.com/feeds/499229115784988201/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=18337532&amp;postID=499229115784988201" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/499229115784988201?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/499229115784988201?v=2" /><link rel="alternate" type="text/html" href="http://thith.blogspot.com/2006/10/what-makes-api-good.html" title="What makes an API good" /><author><name>Truong Hong Thi</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00479434843416697005" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C0cGSHs9eip7ImA9WBBQFUU.&quot;"><id>tag:blogger.com,1999:blog-18337532.post-4316540397277890226</id><published>2006-10-26T16:45:00.000+07:00</published><updated>2006-11-15T15:57:09.562+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2006-11-15T15:57:09.562+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ideas" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><category scheme="http://www.blogger.com/atom/ns#" term="Exception" /><title>Why exception so verbose?</title><content type="html">&lt;p&gt;I remember, on my first days with VS.NET, I wanted to add some exception  classes to my project. I launched the &lt;i&gt;Add New Item&lt;/i&gt; dialog trying to find some item  like exception. There was no such item (it even did not have an item for  interface! - VS2005 fixed this). I had to add a regular class, typed in the code for its standard  constructors, then copied and pasted to create other exception classes. Although  my application used a bunch of exceptions, none of them contained additional  fields or methods - just the standard constructors. The way current languages  support exception make exception's type so important and often solely adequate.&lt;/p&gt; &lt;p&gt;Later, I figured out how to add a template into VS.NET and made it appear on  the &lt;i&gt;Add New Item&lt;/i&gt; dialog. Since then, I did not have to manually type the  exception code again (except for the infrequent case when I want to add some  extra stuff into the exception).&lt;/p&gt; &lt;p&gt;However, every time I look at the code of a "standard" exception, I keep  asking myself why on earth it has to be so verbose? Wouldn't it be neater to be  one-line concise like this:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public exception&lt;/span&gt; MyException;&lt;/pre&gt;&lt;p&gt;or if the exception should have a parent other than &lt;code&gt;System.Exception&lt;/code&gt;:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public exception&lt;/span&gt; MySpecificException: MyException;&lt;/pre&gt;&lt;p&gt;The compiler will compiles it into a "standard" exception. This is  essentially the way &lt;code style="color: rgb(0, 0, 255);"&gt;delegate&lt;/code&gt; keyword in C# works.&lt;/p&gt; &lt;p&gt;Then you and me - the code typists - will have some time for a cup of tea.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18337532-4316540397277890226?l=thith.blogspot.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/oAvCOVbBHOA2yO0GDzmuO2wUttg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oAvCOVbBHOA2yO0GDzmuO2wUttg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/oAvCOVbBHOA2yO0GDzmuO2wUttg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oAvCOVbBHOA2yO0GDzmuO2wUttg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thith?a=pHXTsF11hy4:BTXXYVD52ak:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thith?a=pHXTsF11hy4:BTXXYVD52ak:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?i=pHXTsF11hy4:BTXXYVD52ak:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://thith.blogspot.com/feeds/4316540397277890226/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=18337532&amp;postID=4316540397277890226" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/4316540397277890226?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/4316540397277890226?v=2" /><link rel="alternate" type="text/html" href="http://thith.blogspot.com/2006/10/why-exception-so-verbose.html" title="Why exception so verbose?" /><author><name>Truong Hong Thi</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00479434843416697005" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEIDRXs5eip7ImA9WBBQFUQ.&quot;"><id>tag:blogger.com,1999:blog-18337532.post-113090707992234985</id><published>2005-11-02T11:37:00.000+07:00</published><updated>2006-11-15T19:09:34.522+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2006-11-15T19:09:34.522+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Threading" /><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>C# Interlocked</title><content type="html">Multithread programming, together with unit testing and exception handling, is among the tough and hard-to-do-cleanly things a software developer has to do on virtually every project. When starting learning about threads, a developer usually spend a lot of time to figure out how to create, start, and stop threads, how to make use of the thread pool, how to programming with the asynchronous delegates, etc. However, as I see it, the hardest thing to master is thread synchronization, that is, when and where you need to lock a code block to ensure accuracy and consistency. However, locking is reputed as expensive as it is often used ineffectively and create performance bottlenecks in the application.

Effective locking primarily refers to locking at the correct level and correct granularity. Quite often, low level locking becomes useless as higher level code has its own business rules and may requires to lock a chunk of methods-something like "integration locking". Sometimes, two blocks of code are wrongly guarded by the same object which results in unnecessary contention. I am not a fan of lock-free tricks as it is too difficult to understand and might even be proven incorrect some time. However, there are some circumstances in which avoiding locking is just simple and elegant.

I guess some of you might have seen code like following:
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;lock&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;)
{
    a++; &lt;span class="rem"&gt;// or a--, a = b, you name it&lt;/span&gt;
}&lt;/pre&gt;We all learned that even a simple operation like increment might include several steps: load the variable into a register, increment it, save its value back from the register. So the lock in the code snippet above is necessary to prevent some other thread from intervening those steps
(for this to work, the two threads must be guarded by the same lock). The only comment you might make about that snippet is that: avoid locking on &lt;code&gt;this&lt;/code&gt; (or any public object if it is not designed for that purpose) since it might be accidentally be locked on by other code for a different purpose, which usually leads to a deadlock or at least execution inefficiency.

However, the .NET does provide a brilliant class called System.Threading.Interlocked. This class contains a handful of useful methods such as assignment and increment/decrement, each one is performed as an atomic operation. So the above code could be better rewritten as simple as: Interlocked.Increment(ref a). How nice!

"Atomic operation" is sometimes incorrectly interpreted as volatility. Let's take a look at section 5.5 of the &lt;a target="_blank" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html/csharpspecstart.asp"&gt;C# Language Specification&lt;/a&gt; which said:
&lt;i&gt;
&lt;b&gt;5.5 Atomicity of variable references&lt;/b&gt;
Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types. In addition, reads and writes of enum types with an underlying type in the previous list are also atomic. Reads and writes of other types, including long, ulong, double, and decimal, as well as user-defined types, are not guaranteed to be atomic. Aside from the library functions designed for that purpose, there is no guarantee of atomic read-modify-write, such as in the case of increment or decrement.
&lt;/i&gt;
Hmm...  atomic again. Does that means in C#, the two following snippets are identical?

Variables a, b, c are declared at class level:
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; a, b, c;&lt;/pre&gt;Snippet 1:
&lt;pre class="csharpcode"&gt;a = 1;
b = c;&lt;/pre&gt;Snippet 2:
&lt;pre class="csharpcode"&gt;Interlocked.Exchange(&lt;span class="kwrd"&gt;ref&lt;/span&gt; a, 1);
b = c;&lt;/pre&gt;The answer is no. An atomic operation is indivisible. For example, an atomic write guarantees that no other thread can read while the write operation not yet finished and end up reading a partially updated value. However, for performance reason, the JIT, the CLR, or the hardware may decide to apply some optimizations such as reordering or even eliminating instructions as long as they do not break the logic from a single thread's perspective. For instance, in snippet 1, the processor might decide to fetch the value of &lt;code&gt;c&lt;/code&gt; before writing &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;a&lt;/code&gt;. That is OK if the program is single-threaded. However, what if a second thread updates the value of &lt;code&gt;c&lt;/code&gt; in the meantime? The first thread then uses a stale value of &lt;code&gt;c&lt;/code&gt;. The Interlocked class is just more than atomicity. In fact, each one of its methods uses a memory barrier which prevents any instruction being reordered crossing the barrier. The Interlocked.Exchanged method call in snippet 2 prevents the reading of &lt;code&gt;c&lt;/code&gt; before &lt;code&gt;1&lt;/code&gt; is written to &lt;code&gt;a&lt;/code&gt;. Interlocked class is also safe on multiprocessor systems, where, because of caching issues, the sequence of instructions executed on one processor can appear to be different from other processors' perspective.

In addition, the specification says C# does not guarantee functions such as increment and decrement to be atomic. The Interlocked class provides two super-handy methods for those purposes: Interlocked.Increment and Interlocked.Decrement. It should be noted that there are overloaded versions of these two methods that accept a long argument. This surprised me at first since it guarantees increment and decrement of a 64-bit number as an atomic operation.
However, I soon realized that there is no magic under the scene since MSDN remark section of this method says that &lt;i&gt;"The 64-bit versions of Increment and Decrement are truly atomic only on systems where a System.IntPtr is 64 bits long. On other systems, these methods are atomic with respect to each other, but not with respect to other means of accessing the data.”&lt;/i&gt;. Aha, that means on 32-bit systems, they can only be considered atomic only if increment and decrement are the two only operations you ever want to perform on the variable. That
behavior could be simulated by letting the two methods acquire a lock on the same static internal object.

Besides the methods above, Interlocked class also provides a less-used method: CompareExchange. This method, as its name suggests, carries out a comparison first, and then exchanges the values if that test succeeded. Note that compare and exchange operations are performed as a single atomic operation. The &lt;a target="_blank" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemthreadinginterlockedclasscompareexchangetopic1.asp"&gt;example MSDN provides&lt;/a&gt; for this method is very interesting. This method reminds me of the DB optimistic concurrency problem which I had to deal with recently: you should only update a value if it is not been updated by someone else since the last time you queried it. Otherwise, that updated value will be replaced by your value. This method can also be used to implement the Singleton pattern:
&lt;pre class="csharpcode"&gt;Interlocked.CompareExchange(&lt;span class="kwrd"&gt;ref&lt;/span&gt; singleton,
           &lt;span class="kwrd"&gt;new&lt;/span&gt; SingletonClass(), &lt;span class="kwrd"&gt;null&lt;/span&gt;);&lt;/pre&gt;However, this approach requires a new instance of SingletonClass to be created even if &lt;code&gt;singleton&lt;/code&gt; is not &lt;code&gt;null&lt;/code&gt;.

So now if you ever want to lock a block of code which performs only a simple operation on a variable, let’s first see if you can get the same effect with Interlocked class.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18337532-113090707992234985?l=thith.blogspot.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aNWvlS82lo_tjkkOV7l9q2lEbU4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aNWvlS82lo_tjkkOV7l9q2lEbU4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aNWvlS82lo_tjkkOV7l9q2lEbU4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aNWvlS82lo_tjkkOV7l9q2lEbU4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thith?a=0vHvdJQ6nDQ:C5fsnYqnU1Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thith?a=0vHvdJQ6nDQ:C5fsnYqnU1Y:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?i=0vHvdJQ6nDQ:C5fsnYqnU1Y:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://thith.blogspot.com/feeds/113090707992234985/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=18337532&amp;postID=113090707992234985" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/113090707992234985?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/113090707992234985?v=2" /><link rel="alternate" type="text/html" href="http://thith.blogspot.com/2005/11/c-interlocked.html" title="C# Interlocked" /><author><name>Truong Hong Thi</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00479434843416697005" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">9</thr:total></entry><entry gd:etag="W/&quot;DkEFRX0_cCp7ImA9WxJQEEU.&quot;"><id>tag:blogger.com,1999:blog-18337532.post-113049060532234517</id><published>2005-10-28T16:06:00.003+07:00</published><updated>2009-05-23T20:16:54.348+07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-23T20:16:54.348+07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Outsourcing" /><category scheme="http://www.blogger.com/atom/ns#" term="Japan" /><title>A Touch of Japan</title><content type="html">&lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;October 2005. The first time I visited &lt;st1:place st="on"&gt;&lt;st1:country-region st="on"&gt;Japan&lt;/st1:country-region&gt;&lt;/st1:place&gt; was also the first time I went abroad. The initial feeling when the plane was about to land at Narita airport was about the peace and tranquility here. It was slightly cold. I got straight to Hitachi Software building and my one-month working onsite here began.&lt;br&gt;
&lt;br&gt;
However, everything soon turned to be some kind of frustration. Japanese people seemed to be too shy to start conversation, and it was rare to find someone who can speak English well. It took me some time to get used to the railway system. I wish they used Romaji (the alphabetic representation of Japanese) instead of Kanji and Hiragana letters on their maps.&lt;br&gt;
&lt;br&gt;
As having out-sourced for companies in both the &lt;st1:country-region st="on"&gt;US&lt;/st1:country-region&gt; and &lt;st1:country-region st="on"&gt;&lt;st1:place st="on"&gt;Japan&lt;/st1:place&gt;&lt;/st1:country-region&gt;, I feel tempted to make a comparison of the two. Most Japanese could read English well, but their writing, speaking, and listening are usually limited and insufficient to work with offshore teams in English. Plus, they seem to be too shy about their English and prefer to use Japanese even if they can speak English pretty well. As a result, a lot of effort have to be put in communication, and delaying and misunderstanding often occurs. Another thing is that many Japanese companies still make use of old software technologies, architectures, and processes, even when building new systems. One of the reason is that these systems have to inter-operate with legacy ones. However, as I see it, it is also because of their "legacy way of thinking". Japanese companies often consider that it is safer to use old methods, which are guaranteed to work but not very flexible and reusable. I must say that sketching out the system architecture, analyzing and designing in an object-oriented manner, and refactoring the code are among my favorite stuff. However, with Japanese companies I don’t have much chance to do them. A Japanese company often requires many kinds of reports and metrics, and it takes hours to explain them why a simple item of data does not match their norm.&lt;br&gt;
&lt;br&gt;
I am waiting for the weekend when I could go and see something interesting in &lt;st1:city st="on"&gt;Tokyo&lt;/st1:City&gt; and &lt;st1:city st="on"&gt;&lt;st1:place st="on"&gt;Yokohama&lt;/st1:place&gt;&lt;/st1:City&gt;. Geee&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18337532-113049060532234517?l=thith.blogspot.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QS69c6kHZKYRhl5doQ1D5j4tqL4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QS69c6kHZKYRhl5doQ1D5j4tqL4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QS69c6kHZKYRhl5doQ1D5j4tqL4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QS69c6kHZKYRhl5doQ1D5j4tqL4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/thith?a=UsjFRazM1nc:TiPI5Ij9N5Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/thith?a=UsjFRazM1nc:TiPI5Ij9N5Q:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/thith?i=UsjFRazM1nc:TiPI5Ij9N5Q:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://thith.blogspot.com/feeds/113049060532234517/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=18337532&amp;postID=113049060532234517" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/113049060532234517?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/18337532/posts/default/113049060532234517?v=2" /><link rel="alternate" type="text/html" href="http://thith.blogspot.com/2005/10/touch-of-japan.html" title="A Touch of Japan" /><author><name>Truong Hong Thi</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00479434843416697005" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry></feed>
