cast 的个人资料nonocast ! 真诚原是一种需要坚强不屈的...照片日志列表更多 ![]() | 帮助 |
|
|
1月29日 Hope it helps -_-!发现21世纪还是需要跟不同的人不停的解释UTF8,而却一再遭到很奇怪的眼神。
string s = "hello world,日后再说!";
byte[] asciiBytes = Encoding.ASCII.GetBytes(s); Console.WriteLine(ByteHelper.ToString(asciiBytes)); // 68 65 6c 6c 6f 20 77 6f 72 6c 64 2c 3f 3f 3f 3f 21
byte[] unicodeBytes = Encoding.Unicode.GetBytes(s); Console.WriteLine(ByteHelper.ToString(unicodeBytes)); // 68 00 65 00 6c 00 6c 00 6f 00 20 00 77 00 6f 00 72 00 6c 00 64 00 2c 00 e5 65 0e 54 8d 51 f4 8b 21 00
byte[] utf8Bytes = Encoding.UTF8.GetBytes(s); Console.WriteLine(ByteHelper.ToString(utf8Bytes)); // 68 65 6c 6c 6f 20 77 6f 72 6c 64 2c e6 97 a5 e5 90 8e e5 86 8d e8 af b4 21
注意:3f就是'?' 很多时候看到老外的软件也经常处理不好中文,就是因为ASCII编码以至于出现'?',尤其在编辑器和网络中(字符串和byte转换过程)丢失了数据 1月28日 Ftp Uploader Domain Design设计需求: 1.将文件上传至Ftp 2.异步 3.被动进度查询 4.完成通知 5.异常
对象及职责: FtpSite 肉鸡,保存ftp信息 FileUploader 管理并调度上传任务 [Singleton] FileUploadTask 负责将文件上传至Ftp并提供相应信息
========================= Test Driven Code ============================================= FileUploader.Instance.StartUp();
FtpSite site = new FtpSite { FriendlyName = "Test Repo", Uri = "ftp://localhost", UserName = "gbvision", Pwd = "gbvision" };
FileUploadTask task1 = new FileUploadTask { SourceFile = @"C:\Users\nonocast\Desktop\FTP\test1.rmvb", Destination = site, NameStrategy = NameStrategy.GUID, Completed = t => Console.WriteLine("{0} is Completed!", t.SourceFile) };
FileUploadTask task2 = new FileUploadTask { SourceFile = @"C:\Users\nonocast\Desktop\FTP\test2.rmvb", Destination = site, NameStrategy = NameStrategy.GUID, Completed = t => Console.WriteLine("{0} is Completed!", t.SourceFile) };
FileUploader.Instance.Request(task1); FileUploader.Instance.Request(task2);
while (FileUploader.Instance.ActiveTasks.Count > 0) { FileUploader.Instance.ActiveTasks.ForEach( task => Console.WriteLine("{0}%\t{1}/{2}", task.Progress, task.CommitBytes, task.FileSize) ); Console.WriteLine("---------------------------");
Thread.Sleep(1000); }
FileUploader.Instance.ShutDown(); 1月23日 One of my strange dream is ...在CodeProject上看到一篇文章,顺大便看了最下面的About Him
| Microsoft Certified Solution Developer (.NET) working with a software development company in India. | Achieved Masters in Computer Applications and Bachelor degree in Electronics Areas of interest: AI..specifically Genetic Algorithms, Machine learning, automation engineering, user interface designs, human computer interaction, biotechnology, nanotechnology, networking technologies (computers as well as social) One of my strange dreams that I want to come true in my lifetime: Interacting with the computer without opening the eye and without lifting a finger (and ofcourse without having holes in your bodies like the Matrix) 9月29日 foreach & ForEach support并不是只有List<T>才有foreach/ForEach的权利,我们也同样很轻松的实现它 public class ForEachSupport { static void Main(string[] args) { Console.WriteLine("foreach & ForEach support");
EnumerableClass<Document> ec = new EnumerableClass<Document>(); ec.link(Document.create("hello")); ec.link(Document.create("world")); ec.link(Document.create("!!!"));
foreach(Document each in ec) { Console.WriteLine(each.Title); }
ec.ForEach(delegate(Document each){ Console.WriteLine(each.Title); });
Console.ReadLine(); } }
实现也很简单,
public class EnumerableClass<T> : IEnumerable<T> { private List<T> collection = new List<T>();
public IEnumerator<T> GetEnumerator() { foreach (T each in collection) { yield return each; } }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public void ForEach(Action<T> action) { collection.ForEach(action); }
public void link(T entity) { collection.Add(entity); } }
that's ok, all of it. 7月27日 一不小心BlockDataSource = new BlockDateOrderFilter( new BlockDataSource( new SpecifyDateRangeEntryVODataSourceFilter( new SpecifyUserEntryVODataSourceFilter( new EntryVODataSource(SpringContext.getManagerFactory().getEntryManager()), SpecifyUser ), new LastWeek() ) ), true ); 7月25日 generate Code Snippet @ vs2005说实话看到xml就有些晕,不过相对于不断的重复
static readonly ILog logger = LogManager.GetLogger(typeof(DataSourceConcurrencyTest));
总是相对好些。
vs2005采用了snippet生成策略,使用xml来制定规则
直接看一下for和prop你就很容易写出上面的logger生成snippet,如下
<?xml version="1.0" encoding="utf-8" ?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <Title>logger</Title> <Shortcut>logger</Shortcut> <Description>Code snippet for 'log4net' declaration</Description> <Author>Survivalsoft Corporation</Author> <SnippetTypes> <SnippetType>Expansion</SnippetType> <SnippetType>SurroundsWith</SnippetType> </SnippetTypes> </Header> <Snippet> <Declarations> <Literal> <ID>ClassName</ID> <Default>ClassName</Default> <ToolTip>ClassName</ToolTip> </Literal> </Declarations> <Code Language="csharp"><![CDATA[static readonly ILog logger = LogManager.GetLogger(typeof($ClassName$));]]> </Code> </Snippet> </CodeSnippet> </CodeSnippets> 重点就落在最后的<Decarations>和<Code>上,没什么难度,只是xml让我心里堵得慌。
不妨打开VIM,然后在cmd中输入,
:map <F5> 0idef <Esc>oend<Esc>O<Space><Space>
很轻很自由,我想这才是我想要的,呵呵
== update another snippet <Snippet> <Declarations> <Literal> <ID>name</ID> <ToolTip>Class name</ToolTip> <Default>SomeTest</Default> </Literal> </Declarations> <Code Language="csharp"><![CDATA[[TestFixture] public class $name$ { [SetUp] public void setUp() { $selected$$end$ }
[TearDown] public void tearDown() { }
[Test] public void test() {
} }]]> </Code> </Snippet>
7月24日 Memory Load测试一下页面数据源的内存情况
[Unit: Byte]
这里的0, 5000 ... 50000是条目数量 测试条目包含500字(U+)的数据 这样的话,基本来说在10000条占用主存26.5M [42.7M-16.2M] 换句话来说,这个数量级上的DataSource可以做到FullInMemory,而无需考虑Virtual Proxy
量化可以使得在不同的level上做出不同的策略,而无需考虑一种AllInOne的BT方法。 这样可以更潇洒,更自如,更因地制宜
PS,第一次用Excel画表,很兴奋,也不知道兴奋什么,呵呵 迟到的度量工作很简单的代码,
public class PerformanceEntry { public static void Main(string[] args) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 50; i++) { sb.Append("零一二三四五六七八九"); } string content = sb.ToString();
List<string> strs = new List<string>();
Console.WriteLine("ready?"); Console.ReadLine();
for (int i = 0; i < 10000; i++) { strs.Add(string.Format("{0}-{1}", content, i)); }
Console.ReadLine(); } }
but,分配这10000个字符串用了多少内存,你清楚吗? ok,我们可以使用Task Manager和Perfmon,他们都是随Windows一起提供的
Task Manager我就不多说了,看图
分配后的情形,
和进程内存使用情况关系最密切的计数器包括:
Mem Usage (内存使用):在线帮助将其称为进程的工作集(尽管很多人称之为驻留集)——当前在主存中的页面集。但是这个数值包含能够和其他进程共享的页面,因此要注意避免重复计算。比方说,如果要计算共享同一个 DLL 的两个进程的总内存占用情况,不能简单地把“内存使用”值相加。 Peak Mem Usage (内存使用高峰值):进程启动以来 Mem Usage(内存使用)字段的最大值。 Page Faults (页面错误):进程启动以来要访问的页面不在主存中的总次数。 VM Size (虚拟内存大小):联机帮助将其称为“分配给进程私有虚拟内存总数。”更确切地说,这是进程所 提交的内存。如果进程保留内存而没有提交,那么该值就与总地址空间的大小有很大的差别。
然后是PerfMon,这个就更加直观,更加专业,使起来也倍顺手 run -> perfmon 来启动PerfMon 删除下方所有的Counter,然后右键添加
这里的表达方式有些另类,of course,也可以说是更加professional,对应关系如下,
然后你就可以得到如下的内存变化,
最后我们可以根据变化前后的Working Set值来计算增量 40.2M - 15.9M / 10000 = 2.4K 也就是说一个长度为500的string占了2.4K,就算是Unicode,不也应该是1000字节嘛,faint!
你可以将配置save起来,存放到svn中,以使整个team可以share这个配置,PERFECT! 7月20日 夺月7月3日 Caller on .NETCaller on .NET
最easy的, public class CallerTest { static public void Main(string[] args) { try { level1(); } catch (Exception ex) { Console.WriteLine(ex); } finally { Console.ReadLine(); } }
static void level1() { level2(); }
static void level2() { StackTrace st = new StackTrace(); if (st.FrameCount > 1) { StackFrame stFrame = st.GetFrame(1); Console.WriteLine(stFrame.GetMethod()); } } }
如果打开fNeedFileInfo开关,new StackTrace(true), 则可以trace到相应的文件名以及行号。
然后我们从对象的角度来观察, public class CallerTest { class Callee { public void callAtCallee() { StackTrace st = new StackTrace(1, true); Console.WriteLine("{0}.{1}", st.GetFrame(0).GetMethod().ReflectedType.Name, st.GetFrame(0).GetMethod().Name); } }
class Caller { public void callAtCaller(Callee ee) { ee.callAtCallee(); } }
static public void Main(string[] args) { try { new Caller().callAtCaller(new Callee()); } catch (Exception ex) { Console.WriteLine(ex); } finally { Console.ReadLine(); } } }
其中st.GetFrame(0).GetMethod().ReflectedType.Name是指相应MethodBase所在的Class,而st.GetFrame(0).GetMethod().Name则是方法名称。 这样我们就可以很容易在callAtCallee的方法中的得到调用Class以及方法signature.
至于要得到具体哪个对象调用则好像有些难度... 知道的话给我留个方法吧,谢谢了J 6月20日 中文首字拼音1 /// <summary> 2 /// 获取一串汉字的拼音声母 3 /// </summary> 4 /// <param name="chinese">Unicode格式的汉字字符串</param> 5 /// <returns>拼音声母字符串</returns> 6 public static String Convert(String chinese) { 7 char[] buffer = new char[chinese.Length]; 8 for (int i = 0; i < chinese.Length; i++) { 9 buffer[i] = Convert(chinese[i]); 10 } 11 return new String(buffer); 12 } 13 14 /// <summary> 15 /// 获取一个汉字的拼音声母 16 /// </summary> 17 /// <param name="chinese">Unicode格式的一个汉字</param> 18 /// <returns>汉字的声母</returns> 19 public static char Convert(Char chinese) { 20 Encoding gb2312 = Encoding.GetEncoding("GB2312"); 21 Encoding unicode = Encoding.Unicode; 22 23 // Convert the string into a byte[]. 24 byte[] unicodeBytes = unicode.GetBytes(new Char[] { chinese }); 25 // Perform the conversion from one encoding to the other. 26 byte[] asciiBytes = Encoding.Convert(unicode, gb2312, unicodeBytes); 27 28 // 计算该汉字的GB-2312编码 29 int n = (int)asciiBytes[0] << 8; 30 n += (int)asciiBytes[1]; 31 32 // 根据汉字区域码获取拼音声母 33 if (In(0xB0A1, 0xB0C4, n)) return 'a'; 34 if (In(0XB0C5, 0XB2C0, n)) return 'b'; 35 if (In(0xB2C1, 0xB4ED, n)) return 'c'; 36 if (In(0xB4EE, 0xB6E9, n)) return 'd'; 37 if (In(0xB6EA, 0xB7A1, n)) return 'e'; 38 if (In(0xB7A2, 0xB8c0, n)) return 'f'; 39 if (In(0xB8C1, 0xB9FD, n)) return 'g'; 40 if (In(0xB9FE, 0xBBF6, n)) return 'h'; 41 if (In(0xBBF7, 0xBFA5, n)) return 'j'; 42 if (In(0xBFA6, 0xC0AB, n)) return 'k'; 43 if (In(0xC0AC, 0xC2E7, n)) return 'l'; 44 if (In(0xC2E8, 0xC4C2, n)) return 'm'; 45 if (In(0xC4C3, 0xC5B5, n)) return 'n'; 46 if (In(0xC5B6, 0xC5BD, n)) return 'o'; 47 if (In(0xC5BE, 0xC6D9, n)) return 'p'; 48 if (In(0xC6DA, 0xC8BA, n)) return 'q'; 49 if (In(0xC8BB, 0xC8F5, n)) return 'r'; 50 if (In(0xC8F6, 0xCBF0, n)) return 's'; 51 if (In(0xCBFA, 0xCDD9, n)) return 't'; 52 if (In(0xCDDA, 0xCEF3, n)) return 'w'; 53 if (In(0xCEF4, 0xD188, n)) return 'x'; 54 if (In(0xD1B9, 0xD4D0, n)) return 'y'; 55 if (In(0xD4D1, 0xD7F9, n)) return 'z'; 56 return '\0'; 57 } 58 59 private static bool In(int Lp, int Hp, int Value) { 60 return ((Value <= Hp) && (Value >= Lp)); 61 } 62
Usage: Convert("中国") => z 6月10日 一点点关于window command linetest.rb
----------------------------------------------------------------------
require 'pp'
pp ARGV.length pp ARGV test.cmd
----------------------------------------------------------------------
@ruby "F:\nowProject\smooth\script\test.rb" %*
然后在nonocast/sendto中加入test.cmd的快捷方式
通过测试发现
如果我选中20个文件然后发送到test.cmd,这20个文件就会以20个字符串传到我的rb里面
过去因为老是看到
xxx.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
一直以为最多只带9个参数,呵呵
原来可以蛮多的
其实是很简单的问题,但可以做出一些比较有用的功能,呵呵
在参数和重定向间,我原来一直更倾向于重定向,因为这样的耦合可以更低
但今天就发现重定向固然有他的好处,但限制也是同样多的
比如不能得到源的一些信息,文件类型啦,格式啊
这里的话参数就更加有优势
再次从一个方面证明了没有最好的,只有适合的
大家手牵手,生活很美好! 5月19日 连接1. flash <- js -> dotnet
flash.(v8)
---------------------------------------------- 使用ExternalInterface来和js沟通 非常容易:) 首先需要
import flash.external.*; flash -> js
ExternalInterface.call("methodNameInJs", param1, param2); 没有参数就直接 ExternalInterface.call("methodNameInJs"); 就ok了 flash <- js
ExternalInterface.addCallback("methodAliasNameInAs", null, methodNameInAs); function methodNameInAs(param1, param2, param3) { }
这里需要注意的是AS和JS都是区分大小写的
js
------------------------------------------------ js -> flash 首先得到flash对象 function thisMovie(movieName) { if (navigator.appName.indexOf("Microsoft") != -1) { return window[movieName] } else { return document[movieName] } } 然后调用flash中导出的method就ok了
thisMovie("flashName").methodAliasNameInAs(param1, param2, param3); js <- flash
function methodNameJs(param1, param2) { } js <-> dotnet ...
2. plain text -> ruby -> http post -> dotnet client.
-------------------------------------------------- require 'net/http' require 'uri' data = ""
File.open('data.txt') do |f| data = f.readlines data.join end res = Net::HTTP.post_form(URI.parse('http://rssvr:88/Default.aspx'), {'data'=>data})
puts res.body
server. --------------------------------------------------- protected void Page_Load(object sender, EventArgs e) { logger.Info(Request.form['data']); } 记得在aspx中Page后面加入ValidateRequest="flase"
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="HttpAnalyse.site._Default" ValidateRequest="false"%>
还有就是编码问题,在Web.config中<system.web>节点中加入
<globalization requestEncoding="GB2312" responseEncoding="GB2312" uiCulture="zh-CN" culture="zh-CN" fileEncoding="GB2312" /> 4月29日 管道的力量如果进程是轻量的,如果IPC是优雅的,那么很自然就会使用多种语言协同作业
但如果进程是重量的,IPC是扭曲的,那么很自然的就会使得线程看上去是那么的自然,是必然的
那么语言间的协同也就不复存在,如果没有协同那么必定要造无数个重复的轮子,早就无数个大的可怜的project
这就是宿命,在Windows中的悲哀
如果你用C#写一个程序明明一些内容是适合srcipt解决的,但你就是找不到在合适的成本下让他们合作的方式。有把合作的能力早就能用C#完成这些工作了,而且还规避了由pipe或是socket之间产生的不可预料的异常以及不可想象的开销。
进程 管道 重定向 在 SHELL 中跑的是如此欢快
当然也不可避免带来了依赖的复杂度,呵呵
3月31日 xmlSerialize abc在做对象序列化的时候遭遇了一下xml serializer,在dotnet下是非常省心的。 User nonocast = new User("nonocast"); User syy = new User("shenyuyang"); User beatmania = new User("beatmania"); User tony = new User("tonykong"); List<User> users = new List<User>(); users.Add(nonocast.setId<User>(1)); users.Add(syy.setId<User>(2)); users.Add(beatmania.setId<User>(3)); users.Add(tony.setId<User>(4)); XmlSerializer serializer = new XmlSerializer(typeof(List<User>)); serializer.Serialize(new FileStream(@"users.xml", FileMode.Create), users); 这样就可以将对象序列化到users.xml中去了 <?xml version="1.0"?> <ArrayOfUser xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <User id="1"> <Name>nonocast</Name> </User> <User id="2"> <Name>shenyuyang</Name> </User> <User id="3"> <Name>beatmania</Name> </User> <User id="4"> <Name>tonykong</Name> </User> </ArrayOfUser> 这里之所以name是子节点,而id作为属性是因为在id申明的地方加了一句Attribute< br> [XmlAttribute("id")] public int Id { get; set; } 如果需要将对象序列化到string中只需更换相应的strategy就ok了,形如: StringBuilder sb = new StringBuilder(); serializer.Serialize(new StringWriter(sb), users); 反序列化同样也是两句: XmlSerializer serializer = new XmlSerializer(typeof(List<User>)); List<User> users = (List<User>)serializer.Deserialize(new FileStream(@"users.xml", FileMode.Open)); 这样就轻松地完成了xml序列化和反序列化,比c++要爽太多,比yaml还略逊色一些。 比上不足,比下大有余吧:) 3月29日 ss abc 如果只是用鼠标简单的点点vs和vss来做版本管理,可以说需要做大量的重复工作来管理同步dll,以及各个solution之间的依赖关系,尤其是在不同的vss仓库下做一些同步工作。 首先需要升级一下command line下的vss工具ss 上来先看看三个环境变量: SSUSER SSPWD SSDIR ss会根据上面这三个变量来选择相应的vss仓库并登录 一般来说: set SSUSER=nonocast set SSPWD=123456 set SSDIR=//rssvr/vss/survivalsoft ss Create $test.project 即可以在survivalsoft这个vss仓库中添加一个test.project的project,很easy吧.. 一般来说用户名和密码都是相对固定的,可以直接写到环境变量中去 这里可以通过set SSDIR非常容易的切换vss仓库 这个抛砖引玉介绍几条command,具体的可以参考VSS Documentation 1.CP sets the current project path. Syntax: ss CP <project> [-H] [-I-] [-Y] [-?] 通过SSDIR切换仓库,然后通过CP切换project,基本完成project定位 然后就是 2.GET Retrieves read-only copies of the specified Visual SourceSafe files or projects to your working folder. Syntax: ss Get <items> [-G] [-H] [-I-] [-N] [-O] [-R] [-V] [-W] [-Y] [-?] 这里的Get和check out的区别就在于read-only Get的权限级别要比check out低很多 在定位project以后, ss Get * -R 就可以把所有的files全部抓下来 这里的-R是: Used recursively on a project (-R option), this command retrieves all the files in the project and its subprojects, and places them in subfolders of the same name in your working folder. 抓下来的路径就是当前你所在的路径 :) 当然和Get相对应的就是 3.Add Adds new files to the Visual SourceSafe database. Syntax: ss Add <local files> [-B] [-C] [-D-] [-H] [-I-] [-K] [-N] [-O] [-R] [-W] [-Y] [-?] example: Adds all files in the current folder to the current project: ss Add * Adds all files in the current folder and all subfolders to the current project: ss Add *.* -R 最后再给出一些有用的Command Options,其实vss doc上都全,这里给自己一个方便 1.-C Specifies a comment for a command. If you do not specify the -C option, Visual SourceSafe requests a comment for each item specified on the command line. If you do specify the option, all items receive the same comment. 比如说你在create project的时候 ss Create xxxxx 然后他会提示你输入Comment for it: 如果这里用 ss Create xxxxx -C- 他就不放这个P了,所以在bat中还是很实用的一个参数,很多命令都需要配合他来用。 在Add的时候添加新的item,也同样需要-C-去掉输入Comment的提示 2.-I Indicates what factors Visual SourceSafe should ignore when comparing two files. The following table lists ways to use the -I option. 一般来说在做dll的时候不需要比较版本,直接覆盖上去就结了 所以在Add的时候配合-I-一起使用 3.-Y Specifies a user name or user name and password. Use this option if you want to execute a command as another user. -Y<user name> Specifies a user name. -Y<user name>,<password> Specifies a user name and password. 4.-G 这个option就比较牛X了 Sets options for a retrieved working copy. Many of the switches for this option provide command-specific overrides that can be set in the Ss.ini file. -GL<path> Copies a file to the specified folder, not to the current or working folder. Get到指定任意目录。 eg: ss -GLc: Get * 注意这里的路进不能带有空格 小结一下, 如果我要把\\rssvr\vss\survivalsoft中的assembly目录中的所有内容抓到C:\Documents and Settings\nonocast\桌面\lib这个路径中去,命令如下: cd C:\Documents and Settings\nonocast\桌面\lib set ssuser=nonocast set sspwd=123456 set ssdir=//rssvr/vss/survivalsoft ss CP assembly ss Get * -R uups..:) EASY, just abc 如果你觉得bat不爽,也可以用其他script来代替 pull.rb -------------------------------------------------------------------------------------- # must not delete any user's item, just add new or overwrite it require 'ftools' $ssdir='//rssvr/vss/survivalsoft' def sh cmd Kernel::system(cmd) end def update(target) targetDir = File.dirname(__FILE__) + "/#{target}" if !File.directory?(targetDir) File.mkpath(targetDir) end ENV['SSDIR']=$ssdir sh "ss Get $/#{target}/*.dll -GL./#{target}" end if __FILE__ == $0 update("vendor") update("assembly") end ------------------------------------------------------------------------------------- BTW:在环境变量中预先设置了相应的ssuser&sspwd reference web: http://martinfowler.com/articles/ciWithCom.html local: vss documention H:\develop data\General\vss\命令行中使用VSS.txt H:\develop data\专栏\配置\ABSManageSystem.bat hahThe Visual SourceSafe command line utility SS supports most commands available through Visual SourceSafe Explorer, and some that are only available on the command line. The command line is often used by programmers who find typing commands faster than launching Visual SourceSafe Explorer and using menus. Details of the SS utility are provided in SS Utility.
程序员应该勇于直面惨淡的shell,用shell来完成更多的工作,don't be duplicate. 每次的重复让我觉得恶心 组合拳 <= vim+ shell + tool + script 其实利用好tool之间的合作,加上网络可以做出很旋的功能,解决很多很实际的问题
尤其是利用vim+ruby搞一些小的shell script出来 这样不仅轻巧,跨平台,关键是很惬意 在这方面自己还是相当欠缺的 要有一个熟悉的shell,windows下只能凑合用用command,当然考虑升级一下cygwin,但多少还是有些思想上的别扭 shell的关键点在于柔和,协调工作,利用重定向来配合输入输出 再次就是需要熟练掌握vim和ruby语法,尤其是vim的博大精深,加之ruby的灵巧简洁 从扩展来说要熟悉各种周遭的shell工具,熟悉的越多,组合的效能越大 在.net下做项目,免不了多个项目的管理切换 vim+ruby + cmd + ss/csc/msdev 差不多就可以代劳很多体力活了 web: http://martinfowler.com/articles/ciWithCom.html local: H:\develop data\专栏\配置\ABSManageSystem.bat H:\develop data\专栏\配置\Building a Project from the Command Line.txt vss help: Visual SourceSafe Reference - Command Line Reference 3月25日 singleton abc偶然间看到继承的 Singleton模式的实现 想法挺好的,只是觉得为了一个singleton不是太值得,更多是再玩,其实用 Generics用很少的代码就可以走掉的 BTW:这里不考虑multithread,其实 singleton本身属于设计层面,无需涉及线程之类的细节。 class SingletonT<T> where T: new(){ static protected T instance = new T(); static public T getInstance() { return instance; } } class SomeClass : SingletonT<SomeClass> { public void fire() { Console.WriteLine("hello singleton!"); } } class EntryPoint { public static void Main(string[] args) { SomeClass.getInstance().fire(); } } 这里根据个人喜好可以将getInstance()变为Instance { get{..} } 最后当然要感谢diclogic,呵呵 3月23日 event abc习惯在了在C++中肆意PostThreadMessage,到了.net下有些乱了方寸。还好有event,不过千万不要和c#中的那个event搞在一起 // 线程间传送消息 class Program { static AutoResetEvent autoEvent = new AutoResetEvent(false); static Queue<string> messageQueue = new Queue<string>(); static void Main(string[] args) { new Thread(new ThreadStart(messageLoop)).Start(); new Thread(new ThreadStart(threadProc)).Start(); } static void messageLoop() { Queue<string> transferQueue = new Queue<string>(); while (autoEvent.WaitOne()) { // 尽可能的减少messageQueue被锁住的时间 foreach(string msg in messageQueue) { transferQueue.Enqueue(msg); } messageQueue.Clear(); foreach (string msg in transferQueue) { Console.WriteLine(msg); } transferQueue.Clear(); } // while } static void threadProc() { // 可以想象这里是网络的接收线程,客户端在源源不断的向这里发送数据 lock (messageQueue) { messageQueue.Enqueue("Hello Wolrd!"); } autoEvent.Set(); lock (messageQueue) { messageQueue.Enqueue("today is a good day"); } autoEvent.Set(); lock (messageQueue) { messageQueue.Enqueue("let it be "); }autoEvent.Set(); } } 这里的event相当于是一个dirty flag,只要messageQueue加入了message就使这个event激活了,脏一次也是脏,脏两次也是脏 呵呵 这里再简单补充一下event的基本概念,主要参考Win32多线程程序设计 event有两种状态分别是: 激发和未激发 其实就是0,1 有两种使用模式: 手动和自动 手动是指再激发后不会自动重置,必须靠程序操作(调用ResetEvent())才能将其从激发状态设为非激发状态 而自动则表示这个event将在变成激发状态(因而唤醒一个线程)之后,自动重置(reset)为非激发状态 SetEvent: 设为激发状态,Set N次也是激发状态 ResetEvent: 设为非激发状态 从上面的代码可以看到xxxevent.WaitOne就会将event从激发态变为非激发态。 |
|
|