[RIA]RIA项目失败的教训

mikel阅读(673)

EffectiveUI公司主席Anthony Franco最近做了一次名为“RIA项目失败的十种方式”的演讲,为想要RIA项目失败的人提供了十条建议。SAP AG的Gerd Waloszek则总结了“糟糕用户界面的18黄金法则”。

以下是Franco提供的十条逆向建议,并解释了为何要避免它们,而应该如何去做:

  1. 如果你想失败,那就不要理解最终用户——70%的IT项目失败都是由于用户可接受性出了问题。
  2. 如果你想失败,那就相信开发人员能够正确的做出设计决定。开发人员被逼迫着做出糟糕的设计,因为他们的工作量是由其所完成的功能数量决定的。当一个项目将要接近截止日期时,开发人员就会关注于删除功能而不是从最终用户的角度思考。
  3. 如果你想失败,那就期望一个银弹式的设计。好主意是值得肯定的,但一个伟大的功能建议不应该取代优秀健康的UI设计。
  4. 如果你想失败,那就满足所有人的需求。“如果一个公司试图为所有人创造一个产品,那么最后不会适用于任何人”。
  5. 如果你想失败,那就启动项目然后忘却。在项目启动之后,产品需要更多的迭代以不断完善。
  6. 如果你想失败,那就不要定义成功。不定义成功意味着不知道目标是什么。
  7. 如果你想失败,那就避免冲突。冲突未必是坏事,因为“没有冲突就没有进步”。当屋子里的所有人都赞同某种看法时,那么就要提高警惕了。
  8. 如果你想失败,那就相信不需要推销自己的想法。利益相关者应该努力在组织内部推销自己的想法,但不要期望仅仅因为来源于你就会被接受。这需要准备回答类似下面的问题:投资回报率如何?优点是什么?为什么要现在做?如果不做会怎么样?
  9. 如果你想失败,那就追求完美。不应该一开始就把所有都计划好,并期望现实会按照计划行事,因为变化无处不在。
  10. 如果你想失败,那就重视过程甚于产品。这条建议可以改写为:“如果你想失败,那就不要冒险”。我们可以非常重视开发过程,但是“按时生产一个糟糕的产品毫无意义”,通过迭代的方法构建满意的产品更轻松一些。

以下是Waloszek总结的糟糕用户界面18黄金法则,提供了负面的例子:

  1. 让客户忙于那些不必要的工作——让用户在某些控件填写数据,随后又提示他们不能在那里输入数据(比如,一个应用让你在假期或周末填写数据,随后又提示说你不能在那些天工作)。
  2. 不遵守标准——不把菜单条目放置在通常的类别和位置上(比如,在“编辑”菜单中放置“保存”按钮)。
  3. 让软件运行缓慢——有无数的可能性导致软件运行缓慢。比如,你可以在每个用户输入之后包含长时间的验证或者切换。或者你可以强制用户浏览一连串的对话框。
  4. 尽可能地使用缩写,特别是在有足够空间显示完整单词的情况下——使用“dat.”而不是“date”,“Tolky”而不是“Tolerance Key”,“NxOb”而不是“Next Object”,等等还有很多……
  5. 使用技术型语言指导用户——使用UTF-8格式发送URL(需要重启,在MS IE的高级设置里)
  6. 隐藏在用户看来重要和常用的功能——把其藏在用户永远找不到的菜单里。
  7. 让你的应用只支持鼠标——绝不提供任何键盘快捷键
  8. 使用你的应用成为一项挑战——即使用户操作会导致严重的后果也不加以提示。
  9. 脱离最终用户——许多用户有许多的选择,你只提供一个。这倒是可以更快更简单的实现。
  10. 宣扬糟糕的示例——只需要听从本页的其他黄金法则就可以实现。
  11. 花费大量精力设置糟糕的缺省参数:与用户的期望背道而驰,缺省配置极其糟糕、令人厌恶、无用——反正由你决定——在web表单上做缺省设置使用户收到不想要的新闻或者广告,散布他们的地址等等。
  12. 在每次系统重新恢复之后都破坏工作上下文——在系统重启之后取消之前选择的屏幕元素。
  13. 忽略让用户更方便的功能——让他们很辛苦——当用户需要在列表中添加条目时,只允许他们在列表末端插入条目,然后再让用户把条目移动到正确的位置。换句话说,没有提供额外的功能用于直接将条目插入到目标位置。为了增加点情趣,当用户直接把条目移动到目标位置时,应用提示一些伪造的错误,然后把条目插入到末尾。
  14. 不让用户中断消耗时间和/或消耗资源的进程——偷偷启动一个备份或者索引进程,让用户难以取消,也就是说,无视用户的鼠标点击和键盘操作。
  15. 应用不合逻辑——添加一个准备某操作的按钮使用户确认可以做该操作了。这里有一个真实例子:在许多电子邮件应用中,“转发”按钮实际上没有真正执行转发操作,而是做转发之前的准备工作(因为,我们不得不提供收件人地址)。
  16. 时不时的来一次系统崩溃或者让应用僵死——让编辑器或者编辑域在用户事先未预料的情况下僵死,以至于用户还没有来得及保存他们的工作成果,而频繁保存的习惯会浪费宝贵的系统资源。
  17. 尽可能的阻碍用户输入——页面加载也是阻碍用户输入的好机会。在等待的时候,用户可能会与室友聊天、读报或者盯着空屏幕发呆。
  18. 阻碍用户输入,即使没有必要——阻碍用户在图片浏览器更新缩略图的时候输入就是一个很好的例子——没有任何理由阻止用户滚动、选择图片或者发起操作。

是否还有其他失败RIA项目的“优秀”建议,值得不惜一切代价避免呢?
查看英文原文:“Good” Lessons on How To Fail a RIA Project

[缓存]A High Performance Multi-Threaded LRU Cache

mikel阅读(992)

Introduction

A LRU Cache is a key-value based data container that is constrained by size and/or age, removing the least recently used objects first. This algorithm requires keeping track of the most recent time each object is accessed, which can be expensive to ensure the algorithm always discards the least recently used item.

Other LRU Algorithms

Most LRU Caching algorithms consist of two parts: a dictionary and a list. The dictionary guarantees quick access to your data, and the list, ordered by age of the objects, controls the lifespan of objects and determines which objects are to be removed first.

A simple LRU Cache implementation uses a doubly linked list; adding new items to the head, removing items from the tail, and moving any existing items to the head when referenced (touched). This algorithm is good for single threaded applications but becomes very slow in a multi-threaded environment. In a multi-threaded app, every time the linked list is modified, it must be locked. This requires thread locks on insert, read, and delete operations, causing the slowness.

Another algorithm is to mark each item’s age with a timestamp (DateTime or incremented Integer) value when touched. When the cache becomes full, the list of items must be sorted and truncated. This keeps insert and read operations very fast because no locks are required, but makes delete painfully slow (normally O(N * log N), for sorting).

Overview

The algorithm I choose, divides items into time slices I call AgeBags. Items are added to the current AgeBag until the bag becomes full or the designated time span expires, then that AgeBag is closed and the next AgeBag becomes current. Items that are touched are marked with an index of the current bag. When the cache gets too full/old, the oldest AgeBag is emptied, moving any nodes that have been touched to the correct AgeBag and removing the rest of the nodes in the bag. This allows reads to be performed without locking, and makes deletes much faster because only items that are in the oldest AgeBag are ever moved and no real sorting is ever performed.

In this system, even though the exact order of items is not maintained, this is still a true LRU Cache because everything that remains in the oldest bag (after moves are made for the touched items) is removed at the same time. Therefore, no item remains in the cache that is older than the removed items.

My implementation of LRUCache contains two distinct sections which are coded as subclasses. The LifespanMgr class tracks the item usage and determines which items to remove when the cache gets full/old. The Index class provides Dictionary key/value access to all objects stored in the cache. The Index has delegates to calculate the key of any item added to the cache, and to load an item by key/value from an external source.

Instead of storing item nodes in the Index, the Index holds WeakReference objects that point at the item nodes. By doing this, the Index does not prevent items from being garbage collected. This also allows old items to be removed from the AgeBag without having to remove the items from the index. Once a Node is removed from the LifespanMgr, it becomes eligible for garbage collection. The Node is not removed from the Indexes immediately. If an Index retrieves the node prior to garbage collection, it is reinserted into the current AgeBag’s node list. If it has already been garbage collected, a new object gets loaded. If the Index size exceeds twice the cache’s capacity, the Index is cleared and rebuilt.

Locking

Before I get into the code, I should provide a brief explanation of all the locking mechanisms used by the LRUCache:

The first and simplest is the Interlocked class which ensures that increment and decrement operations occur without context switching. This is all that is required to make increment and decrement operations thread safe, and is much faster than other locking methods.

The next locking mechanism is the Monitor class. This class is called whenever you use the C# lock keyword. One method of note is Monitor.TryEnter(obj), which immediately returns a bool specifying if a lock was acquired. Unlike the standard Enter() method, after the first thread gets the lock, all other threads will skip the operation instead of waiting for the first thread to complete. This is good for cases where speed is more important than the action being locked. It is also ideal for cases when the locked code only needs to be performed by one thread.

Collapse
if(Monitor.TryEnter(obj))
try {
//do something if lock is not busy
}
finally {
Monitor.Exit(obj);
}

The last locking mechanism used is ReaderWriterLock. At any given time, it allows either concurrent read access for multiple threads, or write access for a single thread. A ReaderWriterLock provides better throughput than Monitor because of its concurrent read access. Because using ReaderWriter locks can get a little tricky, I use a wrapper class that simplifies locking a provided delegate.

Code Review

Because the LifespanMgr is the most interesting part of the code, I will spend most of the remaining article discussing it; however, the code is highly commented so you shouldn’t have any trouble following the rest of the code.

Collapse
public void Touch()
{
if( _value != null && ageBag != _mgr._currentBag )
{
if( ageBag == null )
lock( _mgr )
if( ageBag == null )
{
// if node.AgeBag==null then the object is not
// currently managed by LifespanMgr so add it
next = _mgr._currentBag.first;
_mgr._currentBag.first = this;
Interlocked.Increment( ref _mgr._owner._curCount );
}
ageBag = _mgr._currentBag;
Interlocked.Increment( ref _mgr._currentSize );
}
_mgr.CheckValid();
}

Each time an indexed item is added or referenced, LifespanMgr.Node.Touch() is called which (re)inserts the node if needed, and points the node's ageBag variable at the current AgeBag. Also, in the touch method, LifespanMgr.CheckValid() is called.

Collapse
public void CheckValid()
{
DateTime now = DateTime.Now;
// if lock is currently held then skip and let next Touch perform cleanup.
if( (_currentSize > _bagItemLimit || now > _nextValidCheck)
&& Monitor.TryEnter( this ) )
try
{
if( (_currentSize > _bagItemLimit || now > _nextValidCheck) )
{
// if cache is no longer valid throw contents
// away and start over, else cleanup old items
if( _current > 1000000 || (_owner._isValid != null
&& !_owner._isValid()) )
_owner.Clear();
else
CleanUp( now );
}
}
finally
{
Monitor.Exit( this );
}
}

CheckValid only performs an action if the AgeBag gets full or the designated time span expires. When either of those cases are met, an optional IsValid() delegate is called which checks the health of the overall cache. If the cache is invalid or out of date, all items in the cache are removed and items will be reloaded the next time an index accesses them. If IsValid returns true, the LifespanMgr.Cleanup() method is called.

Collapse
public void CleanUp( DateTime now )
{
if( _current != _oldest )
lock( this )
{
//calculate how many items should be removed
DateTime maxAge = now.Subtract( _maxAge );
DateTime minAge = now.Subtract( _minAge );
int itemsToRemove = _owner._curCount - _owner._capacity;
AgeBag bag = _bags[_oldest % _size];
while( _current != _oldest && (_current-_oldest>_size - 5
|| bag.startTime < maxAge || (itemsToRemove > 0
&& bag.stopTime > minAge)) )
{
// cache is still too big / old so remove oldest bag
Node node = bag.first;
bag.first = null;
while( node != null )
{
Node next = node.next;
node.next = null;
if( node.Value != null && node.ageBag != null )
if( node.ageBag == bag )
{
// item has not been touched since bag was
// closed, so remove it from LifespanMgr
++itemsToRemove;
node.ageBag = null;
Interlocked.Decrement( ref _owner._curCount );
}
else
{
// item has been touched and should
// be moved to correct age bag now
node.next = node.ageBag.first;
node.ageBag.first = node;
}
node = next;
}
// increment oldest bag
bag = _bags[(++_oldest) % _size];
}
OpenCurrentBag( now, ++_current );
CheckIndexValid();
}
}

Cleanup does the grunt work of moving touched items out of the last bag and deleting the rest. It also calls CheckIndexValid() to see if indexes need to be recreated, and OpenCurrentBag() which sets up the next current AgeBag.

Usage

The UserCache.cs file contains an example of how the cache can be used:

Collapse
/// <summary>retrieve items by userid</summary>
public UserData FindByUserID( int userid )
{
return _findByUserID[userid];
}
/// <summary>retrieve items by username</summary>
public UserData FindByUserName( string username )
{
return _findByUserName[username];
}
/// <summary>constructor creates cache and multiple indexes</summary>
private UserCache() : base( 10000, TimeSpan.FromMinutes( 1 ),
TimeSpan.FromHours( 1 ), null )
{
_isValid = IsDataValid;
_findByUserID = AddIndex<int>( "UserID", delegate( UserData user )
{ return user.UserID; }, LoadFromUserID );
_findByUserName = AddIndex<string>( "UserName", delegate( UserData user )
{ return user.UserName; }, LoadFromUserName );
IsDataValid();
}

Summary

This implementation of LRUCache attempts to provide a fast, reliable access to recently used data in a multithreaded environment.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

brian_agnes

Member
Brian Agnes has been professionally programming for 15 years using a variety of languages. Brian started using C# in 2002 and is a MCAD charter member.
Brian is currently living in Denver Colorado and working as a Senior Developer for NewsGator.com (a leader in RSS aggregation).
Brian has been a regular presenter at local INETA dot net user groups.

Occupation: Software Developer (Senior)
Company: NewsGator.com
Location: United States United States

[SQL]品味SQL Server 2005的几个新功能

mikel阅读(786)

SQL Server 2005相对于SQL Server 2000改进很大,有些还是非常实用的。举几个例子来简单说明 这些例子我引用了Northwind库。

  1. TOP 表达式

  SQL Server 2000的TOP是个固定值,是不是觉得不爽,现在改进了。

  –前n名的订单

declare @n int
set @n = 10
select TOP(@n) * from orders 

  2. 分页

  不知各位过去用SQL Server 2000是怎么分页的,大多都用到了临时表。SQL Server 2005一句话就支持分页,性能据说也非常不错。

  –按Freight从小到大排序,求20到30行的结果

select * from(select orderId, Freight, ROW_NUMBER() OVER(order by Freight) as row from orders) a
where row between 20 and 30 

  3. 排名

select * from(select orderId, Freight, RANK() OVER(order by Freight) as rank from orders) a
where rank between 20 and 30 

  4. try … catch

  SQL Server 2000没有异常,T-SQL必须逐行检查错误代码,对于习惯了try catch程序员,2005是不是更加亲切:

SET XACT_ABORT ON — 打开 try功能
BEGIN TRY
begin tran
insert into orders(CustomerId) values(-1)
commit tran
print 'commited'
END TRY
BEGIN CATCH
rollback
print 'rolled back'
END CATCH 
 

5. 通用表达式CTE

  通过表达式可免除你过去创建临时表的麻烦。

  –例子:结合通用表达式进行分页

WITH orderFreight AS(
select orderId, Freight, ROW_NUMBER() OVER(order by Freight) as row from orders
)
select orderId, Freight from orderFreight where row between 10 and 20 

  特别,通过表达式还支持递归。

  6. 直接发布Web Service

  想要把store procedure变成Web Service就用这个吧,.net, IIS都不需要,通过Windows 2003的HTTP Protocol Stack直接发布WebService,用这个功能需要Windows 2003 sp1

–DataSet CustOrdersOrders(string customerID)
Create ENDPOINT orders_Endpoint
state=started
as http(
path='/sql/orders',
AUTHENTICATION=(INTEGRATED),
ports=(clear)
)
for soap(
WebMethod 'CustOrdersOrders'(
name='Northwind.dbo.CustOrdersOrders'
),

wsdl=default,
database='Northwind',
namespace='http://mysite.org/'

  Web Service就发布好了,敲入http://localhost/sql/orders?wsdl得到wsdl 。

[Flex]Adobe新开源2个框架

mikel阅读(802)

今天Adobe官方宣布面向开发者社区开源两个项目,下面是两个项目的具体信息。
第一个项目的名称为OSMF,全称是Open Source Media Framework,开源媒体框架,以前的项目代号是Strobe。其中Akamai和Adobe将基于此OSMF框架共同开发Open Video Player应用。OSMF目的是为了让开发者可以更加容易的创建在线媒体播放应用,同时可以轻松扩展媒体应用之上的广告,监控,报告和内容交付层面的功 能。OSMF开源媒体框架包含了针对合作伙伴使用的API,可以用来在使用OSMF开发的媒体应用上添加功能插件扩展。
OSMF的相关信息:
http://www.opensourcemediaframework.com/
第 二个项目的名称是TLF,全称是Text Layout Framework,文字布局框架。这是一个基于Flash AS3扩展的面向Flash Player 10和AIR 1.5的富文本布局框架,现在也已经Open source,目前纽约时报的Time Reader 2.0,Acrobat.com的在线幻灯和Makebook网站均使用TLF。你可以从这里了解到相关的信息:
http://opensource.adobe.com/wiki/display/tlf/

[VBA]VBA 应用例子

mikel阅读(931)

————————————————————————
宏的使命完成后,能否被自动清除
http://office.9zp.com/dispbbs.asp?boardID=3&ID=482&page=1
作用:宏的使命完成后,能够被自动清除
————————————————————————
VBA工具-commandbar ID列表
http://office.9zp.com/dispbbs.asp?boardid=3&replyid=116&id=116&page=1&skin=0&Star=1
作用:可获取 commandbar ID 列表
————————————————————————
类别是什么?
http://office.9zp.com/dispbbs.asp?BoardID=3&ID=4930&replyID=15612&skin=1
作用:类别是对象的定义。其中包含对象动作行为的相关信息,包括对象的名称、方法、属性和事件……
     让你了解类别的概念。
———————————-
CoolButton_类模块学习范例
http://office.9zp.com/dispbbs.asp?boardID=3&ID=4954&page=1
作用:研究了一下界面美化的帖子,其中不少都涉及到了个性化按钮的这个共同问题,于是写了一个通用一点的CCoolButton类,是对Label+Image模拟不同类型的个性化按钮的一个总结,对于ldhyob斑竹的超酷圆形按钮和其他类似的个性化按钮都可以适用
———————————-
关于用类模块实现控件数组
http://office.9zp.com/dispbbs.asp?boardid=3&id=5483&star=1#5483
作用:用类模块实现控件数组
————————————————————————
窗体、控件相关
———————————-
用IMAGE控件做精美圆形钮
http://office.9zp.com/dispbbs.asp?BoardID=3&replyID=683&id=181&skin=0
作用:用IMAGE控件做精美圆形钮
———————————-
用户认证窗口
http://office.9zp.com/dispbbs.asp?boardID=3&ID=4049&page=6
作用:可达到:
1.启动后只显示登录窗口,隐藏程序界面;
2.按"认证登陆窗口"右上角的"X"按钮和右键弹出菜单无效,以防止绕过"认证"关卡;
3.管理员可直接在Sheets("0")中设置各用户的权限.
————————————
有关textbox\listbox框的问题
http://office.9zp.com/dispbbs.asp?BoardID=3&replyID=473&id=119&skin=0
作用:扩展选定内容的基本单元
————————————
从列表框传数据到表格中
http://office.9zp.com/dispbbs.asp?boardID=3&ID=5266&page=1
作用:双击B列任意行,调出列表框,点击列表框中任一行数据,该行数据即被传送到B:E列末行。
A列的序号亦自动按序添加。
列表框中的数据随着数据源数据的扩大而增加。
————————————
[不随表格滚动的命令按钮]
http://office.9zp.com/dispbbs.asp?Boardid=3&ID=3842&replyID=11571&skin=1
作用:打开本工作簿,会自动建立一个[我的按钮]CommandBar悬浮在表中,不随表格的滚动而动。关闭程序后,[我的按钮]CommandBar自动消失。
鼠标在[我的按钮]之“桃、心、梅、方”按钮上稍做停留,会有按钮提示,点击任一按钮,会有相应动作。
————————————————————————
菜单相关
———————————-
如何建立个性菜单?
http://office.9zp.com/dispbbs.asp?boardID=3&ID=5137&page=1
作用:可屏蔽原来的菜单,可以增减“自定义菜单”中的控制项,或把你的程序放到“MSG1、MSG2”中替换掉原来的命令;
当切换到另一工作簿时,屏蔽自定义菜单,恢复原菜单;切换回本工作簿时,又屏蔽了原菜单,恢复自定义菜单;
当关闭本工作簿时,自动清除自定义菜单,并恢复原来的菜单.
——————————-
关于给自定义菜单加密码的问题
http://office.9zp.com/dispbbs.asp?BoardID=3&replyID=5181&id=5181&skin=0
作用:打开时自动将所有工具栏关闭,并用自建的菜单代替原有菜单。自定义菜单中有一个按钮可以将界面恢复到EXCEL的原样。如果此菜单不希望其他人使用,可为这个菜单设置密码,而且密码可以更改。
————————————————————————
关于Application对象之方法、属性、事件的整理结果
http://office.9zp.com/dispbbs.asp?boardID=3&ID=5065&page=1
作用:关于Application对象之方法、属性、事件的概念
———————————-
EXCEL VBA 事件示例说明
http://office.9zp.com/dispbbs.asp?boardID=3&ID=5029&page=2
作用:EXCEL VBA 事件示例说明
———————————-
CommandBars集合
http://office.9zp.com/dispbbs.asp?boardID=3&ID=5592&page=1
作用:关于CommandBars的使用方法
————————————————————————
用代码实现在桌面创建快捷方式
http://office.9zp.com/dispbbs.asp?boardID=3&ID=4898&page=3
作用:当点击按钮生成了新的工作簿后我还希望能在桌面上自动创建一个与新工作簿同名的快捷方式以方便启动(工作簿的文件名是动态的)。
————————————————————————
各区域数据自动轮换
http://office.9zp.com/dispbbs.asp?boardID=3&ID=3890&page=6
作用:任意选中同样大小的<=五个区域,点击按钮后,选中区域的数据自动顺时针轮换。
————————————————————————
怎么从100个excel工作薄提取我要的第三行的数据汇总成一张工作表?
http://office.9zp.com/dispbbs.asp?boardID=2&ID=3597
作用:可从多个excel工作薄所要的数据汇总成一张工作表
————————————————————————
汇总问题
http://office.9zp.com/dispbbs.asp?BoardID=3&replyID=12621&id=4020&skin=0
作用:添加了所有村的工作表之后,能够自动将每个村的“总表”里的汇总数据添加在翠屏区总表相应的位置(所有表都是一样的)
如再要添加工作簿,都放在《汇总》文件夹中,导入数据时只要打开“翠屏区总表”,点击[导入数据]按钮,即自动导入数据到“翠屏区总表”的相应区域。
————————————————————————
如何统计带填充颜色的单元格数量?
http://office.9zp.com/dispbbs.asp?boardID=2&ID=5240&page=1
作用:统计当前工作表中红色字体的单元格数量
————————————————————————
单元格颜色随着选择点的变化而变化
http://office.9zp.com/dispbbs.asp?BoardID=3&replyID=11923&id=3922&skin=0
作用:单元格选择B列的某行,相应A列的某行随着变色,随着B列选择点的移动,相应A列的的颜色就不断的变化与恢复原色。
————————————————————————
如何把数组公式制作成自定义函数
http://office.9zp.com/dispbbs.asp?boardID=3&ID=5367&page=1
作用:常会用到一些很复杂的数组公式,有没有可能把这个数组公式写在模组里,用自定义函数的方式,把参照取代一下就可用的方法呢?看了此帖就知道。
————————————————————————
图片相关
———————————-
对图片设置公式有什么作用呢?
http://office.9zp.com/dispbbs.asp?BoardID=3&replyID=217&id=44&skin=0
作用:自选图形中的流程,标注图等,赋公式为某一单元格,它里面的文字就会随单元格变化,可增加表的艺术性,可操作性
———————————-
如何把图片插入到一个单元格里面?
http://office.9zp.com/dispbbs.asp?BoardID=2&ID=3967&replyID=12175&skin=1
作用:可以把图片插入到一个单元格里面,如图片较大则自动调整单元格大小……
自动更换图片的问题:
http://office.9zp.com/dispbbs.asp?boardid=3&replyid=13404&id=13404&page=1&skin=0&Star=1
作用:可以使图片适应单元格或单元格合并区域的大小……
———————————-
关于给图片加事件的问题
http://office.9zp.com/dispbbs.asp?boardID=3&ID=5518&page=3
作用:可以在所有的图片里做一个循环,给每个图片加一个宏
———————————-
二个把Range保存为图片文件的示例
http://office.9zp.com/dispbbs.asp?boardID=3&ID=5361
作用:把Range保存为图片文件
————————————————————————
一个用 AddPicture 方法加载图片的小例子
http://office.9zp.com/dispbbs.asp?boardID=3&ID=14719&page=1
作用:点击附件中[加图片]按钮,连加 N 张图片(大小、数量和位置可以自己定),每张图片可单独被拖动。
点击附件中[删图片]按钮,删除本页上的所有图片。
————————————————————————
如何使照片随名字显示
http://office.9zp.com/dispbbs.asp?boardID=3&ID=16634&page=1
作用:输入编号后显示姓名和相应的照片
————————————————————————
如何获得IE收藏夹中的信息?
http://office.9zp.com/dispbbs.asp?boardid=3&replyid=5636&id=5636&page=1&skin=0&Star=1
作用:可以显示出收藏夹(包括子目录中)的信息
————————————————————————
Excel能否查询本机MAC或IP地址
http://office.9zp.com/dispbbs.asp?BoardID=15&replyID=2583&id=2583&skin=0
作用:查询本机MAC或IP地址
————————————-
在VBA中怎获取计算机的 IP 地址?
http://office.9zp.com/dispbbs.asp?boardid=3&id=5886&star=1#5886
作用:有几种获取 IP 地址的方法……
————————————————————————
監控刪除行與列
http://office.9zp.com/dispbbs.asp?BoardID=3&ID=4054&replyID=12853&skin=1
作用:可監控刪除行與列
————————————————————————
怎样用一个进度条指示若干子程序的执行过程
http://office.9zp.com/dispbbs.asp?BoardID=3&replyID=1701&id=364&skin=0
作用:用进度条指示若干子程序的执行过程
————————————————————————
将1-200之间的数随机排序在一列中
http://office.9zp.com/dispbbs.asp?boardid=3&id=6358&star=1#21969
作用:可以将数据随机、无重复地排序在一列中
————————————————————————
经过筛选后按代码号复制到各表
http://office.9zp.com/dispbbs.asp?boardid=3&replyid=6162&id=6162&page=2&skin=0&Star=1
作用:复制筛选后的可见单元格到相应表
————————————————————————
透過按鍵擷取 工作表的數據資料
http://office.9zp.com/dispbbs.asp?boardID=3&ID=6573&page=1
作用:通過按鍵的方式   擷取 02工作表的數據資料
一個按鍵是由上至下
一個則是由下往上
每按一次按鍵  就換一組數據
————————————————————————
EXCEL 2000中在保护状态下进行筛选和排序的例子
http://office.9zp.com/dispbbs.asp?boardID=2&ID=6875&page=1
作用:EXCEL 2000中在保护状态下进行筛选和排序
————————————————————————
取字串中的数字或文本
http://office.9zp.com/dispbbs.asp?boardID=3&ID=6882&page=1
作用:自定义函数。
函数=myTex()可从文本与数字夹杂的字串中只提取其中的文本;
函数=myNum()可从文本与数字夹杂的字串中只提取其中的数字
————————————————————————
一个简单实用的通讯录
http://office.9zp.com/dispbbs.asp?boardID=3&ID=6955&page=1
作用:1.窗体文本框录入,数据存入工作表;
2.listview同步显示录入记 录,单击listview中任一记录,文本框显示该条记录;
3.在窗体文本框中进行修改、删除记录;
4.增加、保存由一个按钮控制;
5.查询窗体可采用模糊多条件查询;
6.组合框设定数据源;
7.按钮控制;
8.禁止窗体右上角关闭按钮
————————————————————————
一个简繁转换代码
http://office.9zp.com/dispbbs.asp?boardID=3&ID=6985&page=1
作用:用自定义函数的形式实现简繁字体的转换
————————————————————————
单元格属性代码
http://office.9zp.com/dispbbs.asp?boardid=3&id=6990&star=1#24236
作用:单元格格式设置、数据类型、对话框、ASCII字符集、单元格显示符号、工作表打印设置的说明
————————————————————————
如何将IE页面先截图然后再放入一个单元格中?
http://office.9zp.com/dispbbs.asp?boardID=3&ID=7647&page=1
作用:将IE页面先截图然后再放入一个单元格中
————————————————————————
[分享]利用 樣式 (Style) + VBA 使儲存格文字閃爍
http://office.9zp.com/dispbbs.asp?boardID=3&ID=7974&page=1
作用:一个比较典型的使用定时器的例子。
————————————————————————
学习Excel 2002 VBA编程和XML,ASP技术
http://office.9zp.com/dispbbs.asp?boardid=3&replyid=7534&id=7534&page=1&skin=0&Star=1
作用:这是本论坛贵宾 hxhgxy 翻译的VBA教程,本教程共有17章。
hxhgxy 认为该教程是最容易懂,最容易上手的VBA教程
————————————————————————
如何用宏将纯文本文件转换为带分隔符的文件
http://office.9zp.com/dispbbs.asp?boardid=3&id=7507
作用:按一定要求修改 *.txt 文件。
————————————————————————
合并不同路径下的文本文件
http://office.9zp.com/dispbbs.asp?boardID=3&ID=14938&page=2
作用:在已有内容的文本文件中添加新内容
————————————————————————
Application.Dialogs(i).Show     '调用对话框
http://office.9zp.com/dispbbs.asp?BoardID=3&ID=8673&replyID=29882&skin=1
作用:对话框索引
————————————————————————
如何用代码增加模块并加入代码?
http://office.9zp.com/dispbbs.asp?BoardID=3&replyID=11145&id=3748&skin=0
作用:大头笑着说:“VBA入门?有一个速成方法:念1000遍"对象,属性,方法,事件"就入门了。”
      这是真的吗……?
————————————————————————
VBA系列讲座
http://info.9zp.com/show.aspx?id=803&cid=10
作用:讲解VBA是什么、excel环境中基于应用程序自动化的优点、录制简单的宏……等
————————————————————————
关于用 Consolidate 方法汇总多表数据
http://office.9zp.com/dispbbs.asp?BoardID=3&ID=13803&replyID=40466&skin=1
作用:此举大大提高了多表汇总的效率。
————————————————————————
将excel内容转贴到word
http://office.9zp.com/dispbbs.asp?boardID=3&ID=14045&page=1
作用:将*.xls中多页的内容转贴到word
————————————————————————
用excel新建一个同已有word模版文件一样的文件
http://office.9zp.com/dispbbs.asp?boardID=3&ID=15362&page=1
作用:读出已存在WORD文件内容另存为一个新WORD文件
————————————————————————
[原创]借助FLASH技术美化VBA操作界面
http://office.9zp.com/dispbbs.asp?BoardID=3&replyID=2636&id=666&skin=0
作用:算法优化了,程序编完了,调试过关了,接下来便是程序界面的设计问题……
————————————————————————
关于整个表格的排序
http://office.9zp.com/dispbbs.asp?boardID=3&ID=15619&page=1
作用:按区域中指定单元格的数字大小,对区域进行排序
————————————————————————
用VBA列出货品清单问题
http://office.9zp.com/dispbbs.asp?boardID=3&ID=15764&page=1
作用:一个在填表单时同时显示填单进度的进度条实例。
————————————————————————
文件的自毁
http://office.9zp.com/dispbbs.asp?BoardID=3&ID=5685&replyID=19019&skin=1
作用:介紹如何讓Excel檔案有使用期限,範例中使用Windows Script"在註冊表上的讀.寫.刪除的用法

[CSS]你应当了解的几个CSS3新技术

mikel阅读(753)

作为一个Web开发者,保持对未来Web标准的关注、学习和了解是很重要的。这里是一些CSS3相关的文章和资源,不管你是第一次准备去认识CSS3,还是已经略知皮毛,下面这些资源都将有助你更好的学习和理解CSS3。

 

英文CSS3资源
CSS3.info
看域名就知道,这是一个专门介绍CSS3的网站。所有你想了解的有关CSS3的信息,都能在这里找到。
CSS3.com
又一个专门介绍CSS3的网站,包含各种CSS3参考文章和教程。
Introduction to CSS3
W3C官方对CSS3的各种详细介绍。

 

CSS3中的几个有趣的新技术:圆角、个别圆角、不透明度、阴影和调整元素大小

 

CSS3   边框效果

 

圆角

CSS3 新功能中最常用的一项是圆角效果,标准 HTML 方块对象是90度方角的,CSS3 可以帮你实现圆角。

 

 

Html代码
  1. -moz-border-radius: 20px;   
  2. -webkit-border-radius: 20px;   

 

甚至单个角也可以实现圆角,不过 Mozilla 和 Webkit 的语法稍有不同。

Html代码
  1. -moz-border-radius-topleft: 20px;    
  2. -moz-border-radius-topright: 20px;    
  3. -moz-border-radius-bottomleft: 10px;    
  4. -moz-border-radius-bottomright: 10px;    
  5. -webkit-border-top-rightright-radius: 20px;    
  6. -webkit-border-top-left-radius: 20px;    
  7. -webkit-border-bottom-left-radius: 10px;    
  8. -webkit-border-bottom-rightright-radius: 10px;    

 

多层边框

border的另一个非常帮的特性是使用gradientcolors,而不是用图片:

Html代码
  1. bordercolor{  
  2.     border: 8px solid #000;  
  3.     -moz-border-bottom-colors: #0fff09 #00fff2 #00ff00 #ffd #ff0 #aaa #bbb #ccc;  
  4.     -moz-border-top-colors:    #0fff09 #00fff2 #00ff00 #ffd #ff0 #aaa #bbb #ccc;  
  5.     -moz-border-left-colors:   #0fff09 #00fff2 #00ff00 #ffd #ff0 #aaa #bbb #ccc;  
  6.     -moz-border-right-colors:  #0fff09 #00fff2 #00ff00 #ffd #ff0 #aaa #bbb #ccc;  
  7.     width:200px;  
  8. }  

 

边框图片

一个令人兴奋的CSS3新的border特性是支持border-image。这样你就能为每一个独立的角和边框定义一个图片。

 

Html代码
  1. border-image:  
  2.     border-top-image  
  3.     border-right-image  
  4.     border-bottom-image  
  5.     border-left-image  
  6.     border-corner-image:  
  7.     border-top-left-image  
  8.     border-top-right-image  
  9.     border-bottom-left-image  
  10.     border-bottom-right-image  

 

 

css3阴影效果

阴影效果曾让 Web 设计师既爱又恨,现在,有了 CSS3,你不再需要 Photoshop

 

Html代码
  1. -webkit-box-shadow: 10px 10px 25px #ccc;    
  2. -moz-box-shadow: 10px 10px 25px #ccc;    
  3. box-shadow: 10px 10px 25px #ccc;     

 

前两个属性设置阴影的 X / Y 位移,这里分别是 10px,第3个属性定义阴影的虚化程度,最后一个设置阴影的颜色。文字阴影也可以这样设置:

 

Html代码
  1. text-shadow: 2px 2px 5px #ccc;    

 

css调整元素的尺寸

在最新版本的CSS中,调整元素的尺寸已经成为可能(不过目前仅Safari支持)

使用这个代码以后,我们的元素的右下角会出现一个小三角以提示用户这个元素是可以调整尺寸的。代码依然很简单,可以说仅需要一行代码,当然你还可以 配合使用一些曾经使用过的属性,比如”max-width”, “max-height”, “min-width”和 “min-height”.

 

Html代码
  1. #resize {  
  2. background-color: #fff;  
  3. border: 1px solid #000;  
  4. resize: both;  
  5. overflow: auto;  
  6. }  

 在这里主要说一下resize和overflow属性,resize:both;的意思就是所有边都可以调整尺寸,它的值还有horizontalvertical ,顾名思义,就是横向和纵向。而overflow是为了配合resize工作的,在这里使用auto.

 

CSS3的方式修改不透明度

现在你可以按惯例编写几行代码来实现不透明度的效果(hack)。不过CSS3简化了这个流程。

这行代码很好记,仅仅是 “opacity: value;”

 

Html代码
  1. #opacity {  
  2. background-color: #000;  
  3. opacity: 0.3;  
  4. }  

 

详解CSS3中的属性选择符
在CSS3中还有功能更加强大的选择符等待我们去发掘和使用。CSS3中的很多选择符已经在现代浏览器中得到很好的应用(IE8.0中也已经部分地 支持了 CSS3),但是这些基本功能上的支持还远远不能满足开发者使用的要求。但是在某些情况下使用他们可以带来很好的超前体验,因此我认为了解一 下CSS 3新增选择符是如何使用还是有益处的。

 

选择符类型 表达式 描述
子串匹配的属性选择符 E[att^="val"] 匹配具有att属性、且值以val开头的E元素
子串匹配的属性选择符 E[att$="val"] 匹配具有att属性、且值以val结尾的E元素
子串匹配的属性选择符 E[att*="val"] 匹配具有att属性、且值中含有val的E元素
结构性伪类 E:root 匹配文档的根元素。在HTML中,根元素永远是HTML
结构性伪类 E:nth-child(n) 匹配父元素中的第n个子元素E
结构性伪类 E:nth-last-child(n) 匹配父元素中的倒数第n个结构子元素E
结构性伪类 E:nth-of-type(n) 匹配同类型中的第n个同级兄弟元素E
结构性伪类 E:nth-last-of-type(n) 匹配同类型中的倒数第n个同级兄弟元素E
结构性伪类 E:last-child 匹配父元素中最后一个E元素
结构性伪类 E:first-of-type 匹配同级兄弟元素中的第一个E元素
结构性伪类 E:only-child 匹配属于父元素中唯一子元素的E
结构性伪类 E:only-of-type 匹配属于同类型中唯一兄弟元素的E
结构性伪类 E:empty 匹配没有任何子元素(包括text节点)的元素E
目标伪类 E:target 匹配相关URL指向的E元素
UI元素状态伪类 E:enabled 匹配所有用户界面(form表单)中处于可用状态的E元素
UI元素状态伪类 E:disabled 匹配所有用户界面(form表单)中处于不可用状态的E元素
UI元素状态伪类 E:checked 匹配所有用户界面(form表单)中处于选中状态的元素E
UI元素状态伪类 E::selection 匹配E元素中被用户选中或处于高亮状态的部分
否定伪类 E:not(s) 匹配所有不匹配简单选择符s的元素E
通用兄弟元素选择器 E ~ F 匹配E元素之后的F元素

 

初探CSS3 RGBA颜色
浏览器的透明一直无法实现 单纯的颜色透明,每次使用alpha后就会把透明的属性继承到子节点上。换句话说,很难实现 背景颜色透明 而文字不透明的效果…直到 RGBA 颜色的出现这一切将成为现实。

 

实现这样的效果非常简单,设置颜色的时候我们使用标准的 rgba() 单位即可, 例如 rgba(255,0,0,0.4) 这样就出现了一个红色同时拥有alpha透明为 0.4的颜色.

 

Html代码
  1. background: rgba(200, 54, 54, 0.5);     
  2. color: rgba(200, 54, 54, 0.5);    

 

CSS3 中的 Gird 布局
刚刚看了一份 W3C CSS3 的文档,是关于 Gird (网格?)布局草案的说明。无论它最终实现是否如草案中的描述,但这个功能本身就已经足够吸引人了。

 

图中蓝色的线不会出现在实际的网页中。对于这个布局复杂的三栏网页来说,如果使用 CSS3 Gird 布局的话,我们只需这样写:

 

Html代码
  1. body { columns:3; column-gap:0.5in; }  
  2. img { float:page top right; width:3gr; }  

 

其中,body 部分声明页面为 3 栏,栏间距为 0.5英寸;img 中 float 属性指明图片浮动位置为页面的右上角(CSS3 定位好强大 -__-),而宽度为 3 个栏宽。只需这样两行 CSS,我们就可以实现这个复杂的布局了。真的很神奇。

Gird 布局是好,不过如果你认为它很简单的话,你就大错特错了。看看 w3c 中关于它的介绍 ,你会发现理解它的意义不亚于看懂天书。好在还是个草案,但愿它到了正式版的时候,能够更加简单易用点。

Gird 布局应用很广泛,最简单的例子就是内容的分栏显示。但这个 CSS3 特性目前还没有任何浏览器可以支持它。谁要是能第一个支持它(以及其它 CSS3 草案),那就酷毙了。不知道,最近异常低调的 IE8,会不会是这第一个吃螃蟹的人呢?

[C#]浅谈线程池(上):线程池的作用及CLR线程池

mikel阅读(762)

  线程池是一个重要的概念。不过我发现,关于这个话题的讨论似乎还缺少了点什么。作为资料的补充,以及今后文章所需要的引用,我在这里再完整而又 简单地谈一下有关线程池,还有.NET中各种线程池的基础。更详细的内容就不多作展开了,有机会我们再详细讨论这方面的细节。这次,还是一个“概述”性质 的,希望可以说明白这方面问题的一些概念。

线程池的作用

  其实“线程池”就是用来存放“线程”的对象池。

   在程序中,如果某个创建某种对象所需要的代价太高,同时这个对象又可以反复使用,那么我们往往就会准备一个容器,用来保存一批这样的对象。于是乎,我们 想要用这种对象时,就不需要每次去创建一个,而直接从容器中取出一个现成的对象就可以了。由于节省了创建对象的开销,程序性能自然就上升了。这个容器就是 “池”。很容易理解的是,因为有了对象池,因此在用完对象之后必须有一个“归还”的动作,这样便可以把对象放回池中,下次需要的时候就可以再次拿出来使用 了。

  例如,我们在使用ADO.NET连接SQL Server时,.NET框架就会自动帮我们维护一个连接池,这就是因为重新创建一个连接的代价相对比较高昂,“复用”就显得比较划算了。不过有些朋友可 能会说,我们明明是每次都创建一个SQLConnection对象,哪里有“复用”啊?这是因为.NET框架中把“连接池”做透明了,对于程序员完全隐藏 了这个概念。每次我们虽然创建的是新的SQLConnection对象,但是这个对象内部占用的“数据库连接”还是会复用的。为什么总是强调用完 SqlConnection对象后要及时“关闭”(Dispose或Close)呢?其实这里并没有断开数据库连接,只是把这个连接放回了连接池。等到下 次创建新的SqlConnection对象时,这个连接又可以拿出来用了。

  既然我们每次都是从池中获取对象,那么这些对象是由谁来创 建,又是什么时候创建的呢?这个就要根据不同情况由各对象池来自行实现了。例如,可以在创建对象池的时候指定池内对象数量,并且一下子全部创建好,当然您 也可以在得到请求时,如果发现池中已经没有剩余对象时创建。您也可以“事前”先准备一部分,“事中”根据需要再继续补充。还可以做得“智能”一些,例如, 根据实际情况添加或删除一些对象,甚至对需求“走势”进行“预测”,在空闲时便创建更多的对象以备“不时之需”。各中变化难以言尽。

  当然,它们的原理和目的是类似的。相信上面这段文字也已经讲清了“线程池”的作用:因为创建一个线程的代价较高,因此我们使用线程池设法复用线程。就是这么简单。

CLR线程池

  在.NET中,CLR线程和操作系统线程对应,您可以简单地认为.NET中的Thread对象便封装了一个操作系统线程,并附带一些托管环境下所需要的数据(如GC Handle)1。而CLR线程池便是存放这些CLR线程的对象池。

   我们在编写程序的时候,可以使用ThreadPool类的两个静态方法:QueueUserWorkItem和 UnsafeUserQueueWorkItem向CLR线程池中添加任务(一个WorkCallback委托对象),这两个方法的区别,在于前者会收集 调用方的ExecutionContext,也就是保留了的当前线程的执行信息(如认证或语言文化等),使任务最终会在“创建”时刻的环境中执行2——后者就不会。因此,如果比较两个方法的绝对性能,Unsafe方法会略胜一筹。但是平时还是建议使用QueueUserWorkItem方法,因为保留执行上下文会避免很多麻烦事情,且这点性能损耗其实算不上什么。

   CLR线程池在.NET框架中的作用很大,除了让程序员使用之外,其他一些功能也会依赖CLR线程池。如 ThreadPool.RegisterWaitForSingleObject方法,或是System.Threading.Timer组件——还有更 重要可能也是更隐藏的:ASP.NET在得到一个请求后,也会将这个请求处理的任务交由CLR线程池去执行——请注意,它们最多只是添加任务而已,并不表 示任务会立即执行。所有添加到CLR线程池的任务都会在合适的时候得以执行——可能马上,也可能要稍等片刻,甚至更久。

  向CLR线程 池添加任务时,任务会被临时放到一个队列中,并在合适的时候执行。那么怎么样才算是“合适的时候”?简单的概括说来,便是线程池内有空闲的线程,或线程池 所管理的线程数量还没有达到上限的时候。如果有空闲的线程,线程池就会立即让它领取一个任务执行。如果是第二种情况,线程池便会创建新的Thread对 象。由于让操作系统管理太多线程反而会造成性能下降,因此CLR线程池会有一个上限。不同的托管环境会设置不同的上限。如在.NET 2.0 SP1之后,普通的Windows应用程序(如控制台或WinForm/WPF),会将其设置为“处理器数 * 250”。也就是说,如果您的机器为2个2核CPU,那么CLR线程池的容量默认上限便是1000,也就是说,它最多可以管理1000个线程同时运行—— 很多情况下这已经是一个很可怕的数字了,如果您觉得这还不够,那么就应该考虑一下您的实现方式是否可以改进了。

  对于ASP.NET应 用程序来说,CLR线程池容量代表了应用程序最多可以同时执行的请求数量。对于托管在IIS上的ASP.NET执行环境来说,这个值由全局配置决定。这个 配置在machine.config文件中system.web/processModel节点中,为maxWorkerThreads属性,它决定了为 单个处理器分配的线程数。如果这个值为40,且机器上拥有4个处理器(2 * 2CPU),那么这台机器目前的配置表示在同一时刻,ASP.NET可以同时处理160个请求。某些参考资料建议您将其修改为每处理器80-100个线 程,这时您只要修改相应的属性值就可以了。

  既然有最大值,也就相应有了最小值,它代表了CLR线程池“总是会保留”的最少线程数量。由于线程会占用资源,如在默认情况下,每个线程将获得1MB大小的栈空间3。 所以如果在系统中保留太多空闲线程对资源也是一种浪费。因此,CLR线程池在使用大量线程处理完大量任务之后,也会逐步地释放线程,直至到达最小值。 CLR线程池的最小线程数量确保了在任务数量较少的情况下,新来的任务可以立即执行,从而省去了创建新线程的时间。在普通应用程序中这个值为“处理器数 * 1”,而在ASP.NET应用程序中这个值配置在machine.config文件中system.web/processModel节点的 minWorkerThreads属性中4

  在某些时候可能会遇到这样的情况:在一个瞬间忽然来大量任务,每 个任务的执行时间说长不长说短不短,不过足以导致线程池快速分配数百个线程。如果这个峰值之后就一片平静,那么势必造成大量空闲的线程,这种开销对性能的 损耗也非常明显。因此,CLR线程池限制了线程的创建速度不超过每秒2个。这样,即使在某个瞬时获得了大量的任务,CLR线程池也可以使用相对较少的线程 来完成所有工作5

  但是,还有一种情况也值得考虑。例如,对于一个比较繁忙的Web应用程序来说,一打开便会 涌入大量的连接。由于线程的创建速度有限,因此可以执行的请求数量也只能慢慢增加。对于这种您预料到会产生大量线程,而且忙碌状况会持续一段时间的情况, 限制线程的创建速度反而会带来损伤效率。这时,您就可以手动设置CLR线程池的最小线程数量。如果此时CLR线程池中拥有的线程数量较少,那么系统就会立 即创建一定数量的线程来达到这个最小值。设置和获取CLR线程池最小线程数量的接口为:

public static class ThreadPool
{
public static void GetMinThreads(out int workerThreads, out int completionPortThreads);
public static bool SetMinThreads(int workerThreads, int completionPortThreads);
}

  这两个接口的作用和使用方式应该足够明显了(不理解的话可以查阅MSDN),其中workerThreads参数便是CLR线程池的最小线程 数,而completionPortThreads涉及到我们下次要讨论IO线程池,在此就不多作展开了。除了设置和读取CLR最小线程数的方法之 外,ThreadPool还包含这些接口:

public static class ThreadPool
{
public static void GetMaxThreads(out int workerThreads, out int completionPortThreads);
public static bool SetMaxThreads(int workerThreads, int completionPortThreads);
public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads);
}

  值得注意的是,无论是设置还是获取到的这些数值,都与处理器数量没有任何关系了。也就是说,在一台2 * 2CPU的机器上运行一个普通的.NET应用程序时:

  • 调用GetMaxThreads方法将获得1000,表示CLR线程池最大容量为1000(250 * 4),而不是250。
  • 调用SetMinThreads并传入100,表示CLR线程池所拥有的最小线程数量为100,而不是400(100 * 4)。

  对于CLR线程池的简单描述就暂时先到这里了。如果您还有什么疑问请提出,我会加以补充。

相关文章

 

注1:严格说来,Thread对象和系统线程对应关系还有些细节上的考虑。例如,Thread对象只有当真正Start了之后,CLR才会创建一个操作系统线程与它绑定。

注2:ExecutionContext是个很重要且很有用的对象,例如,WinForms或WPF的异步任务中操作界面元素抛出异常该怎么办呢?

注3:使用Windows API或Thread类创建线程时可以指定它的栈空间大小,但是CLR线程池中的线程只能使用默认值——不过这个默认值也和托管环境有关,如普通应用程序 默认为1MB,而ASP.NET为250KB,这意味着ASP.NET应用程序相对更容易产生Stack Overflow异常。

注4:可惜的是,对于processModel节点的数据,ASP.NET只会读取 machine.config中的全局配置信息,这意味着我们不能使用web.config为不同应用程序配置不同的参数。如果我们要实现应用程序级别的 配置,那么必须使用ThreadPool类中提供的API进行设置,这点稍后便会提到。

注5:对于这点,您不妨来做一个算术题:线程池内一下子涌入了500个任务,每个任务阻塞或暂停5秒,每个线程占用1MB内存,假设线程池目前为空,且有着足够的容量,此外线程创建速度也足够快,那么在限制及不限制线程创建速度的情况下,完成这些任务需要多少时间和内存空间?

[SVN]SVN命令封装

mikel阅读(736)

1:前言
     最近遇到个问题。就是非技术人员老是问我如何操作SVN。(因为某些发布功能不是技术人员负责的)结果我就老是给他们演示,结果还是老问。哎,命苦啊。哈 哈,还在俺脑袋好使。看到SVN可以用命令行就一劳永逸的给他们封装个客户端。这个客户端老简单了就两个操作。签入和签出。至于何谓签入何谓签出以及更多 的SVN命令建议大家去看我转摘的一篇文章SVN命令概要
2:实现思路
    整体上来说很简单。就是我们启动SVN.exe然后给他们命令。这个命令有几个要素
    A:远程地址{远端要发布的地址}
    B:本地地址
    C:账号
    D:密码
    举个简单的例子。就说签出吧,像svn co –ignore-externals –username dabing –password dabing svn://192.168.100.136/Community/DocumentCenter/images c:\test。这里需要注意的就是命令行中的信息别用空格分隔,因为操作系统会认为是两个命令。在说说签入,svn add c:\test\aa –force svn ci c:\test\aa -m'4045'.这里需要注意两点。一就是我们要想签入必须先把远端代码签入本地然后再在本地添加最后ci到远端。再者就是ci操作的时候-m后的信息 要有。
3:应用
    可执行程序
    源代码

[Flex]FlexMonkey 1.0发布了

mikel阅读(735)

Gorilla Logic公司于 近日发布了FlexMonkey 1.0。FlexMonkey是个面向Flex和AIR应用的开源测试工具,它可以对Flex用户界面功能进行捕获、回放及验证。FlexMonkey能 够生成基于ActionScript的测试脚本,该脚本可以运行在FlexMonkey应用中,也可以运行在持续集成环境中。

Gorilla Logic公司的CEO,同时也是FlexMonkey项目的创建者Stuart Stern与InfoQ的广大读者分享了其对于此次发布的一些想法。首先,他重点谈到了此次发布中最让他感到激动的地方:

我们彻底改写了用户界面以便更加轻松地记录和回放测试,同时增加了屏幕快照功能,它还能将回放过程中需要验证的属性值的快照保存下来。除了测试Flex应 用以外,FlexMonkey 1.0还首度增加了对AIR应用测试的直接支持。现在的FlexMonkey Console本身就是一个AIR应用,既能独立启动,也能以基于浏览器的SWF的方式启动。

接下来,他回答了关于FlexMonkey如何集成Fluint或是FlexUnit 4这一问题:

FlexUnit 4本身是基于Fluint开源项目的。我们之所以选择在FlexMonkey 1.0中生成Fluint代码的原因在于FlexUnit 4现在还没有最后定案。一旦FlexUnit 4的官方版本发布,我们就会生成基于FlexUnit 4的测试。FlexUnit 4是可以运行Fluint测试的,因此现在为Fluint生成的测试将来还可以运行在FlexUnit 4中。

最后,Stu又补充到:

FlexMonkey 1.0是个专业的测试工具,同时它还是免费的。现在我们没有理由在自动化的单元、集成及QA测试中抛弃UI测试了!

请访问http://flexmonkey.gorillalogic.com来下载FlexMonkey或是进一步了解该项目。此外,去年Stuart接受了InfoQ.com的专访,在DrunkOnSoftware.com上有采访视频。

查看英文原文:FlexMonkey 1.0 Released

[开源]Common Template 模板引擎

mikel阅读(781)

项目名称: CommonTemplate
发起时间: 2007年4月
网站http://www.commontemplate.org
代码托管:http://code.google.com/p/commontemplate/
项目介绍:
CommonTemplate是一个模板引擎,用于编译运行CTL模板语言,并且模板可以在Java,.Net,JS等中通用;
其主要目标是作为JSP,ASP.NET等页面技术的另一种选择方案,以保证用简单的语法,良好的结构,不混杂业务逻辑的方式书写页面;
适合于充当Model-View-Controller(MVC)模式应用的View角色,以使能更好的分离页面设计人员与业务开发人员的职责;
也可以作为动态文本生成工具,生成HTML、XML、Mail、Java源代码或其它文本等。
产品信息:
运行平台: JRE1.4以上版本, 操作系统无关.
开发语言: Java
开源协议: Apache Licence 2.0
项目成员:
梁飞(广州)
桂林(上海)
严荣(大连)