2007年8月8日星期三
如果你有一个王葆的宝葫芦,你会向他许什么愿?变形金刚的电影票?100个IPHONE?
也许吧……不过如果是我,会请他给我一个80%完美的程序员。只所以不要一个100%完美的,是因为我害怕我需要写一份100%完美的需求文档,宝葫芦才能100%完美的理解什么是100%完美的程序员。
首先一点,我希望他来面试的时候,技术笔试能答80分以上。当年我找工作的时候,看到一个考官把不合格的试卷全部撕掉,觉得他这样是对应聘者的污辱,所以我不会这样做,我只是会把不入流的试卷和答卷人的简历拿来做草稿纸——最近草稿纸越来越多,让我觉得很对不起我国脆弱的生态环境。真的,大部份技术笔试的题目,都是非常简单的,而且很多时候出试卷的人偷懒从网上找题。所以,面试之前能充分准备一下,其实80分是很容易的。
其次,我希望他的简历至少是诚实的,分的清楚“精通”,“熟悉”,“了解”。我问过很多精通TCP/IP的人,TCP和IP是什么意思,大部份的人回答不知道。这让我觉得就好像一位自称大师的厨子告诉我他不知道猪肉是猪身上的牛肉是牛身上的人肉是人身上的。
然后,我希望他至少真的“精通”某一个方面,可以和我侃侃而谈,主导一次面试的过程,省我在他回答不出问题的时候老逼着自己想编问题,以避免“这么快就结束是不是会太挫伤他的积极性”的出现。
接下来,我喜欢可以和我谈一点抽像的东西的人。这是我的个人倾向,但当每一个面试的人都说“我很喜欢做程序员”,却又说:“我没看过什么深一点的相关书籍”时,我不得不怀疑“程序员”这份工作对他来说只是混口饭吃。我所认识真正喜欢这一行的人,无不是喜欢看一些“稀奇古怪”的计算机读物打发时间,经常头发蓬松,衣冠不整的家伙。(后两条可选,面试的时候不必刻意)
还有,英文阅读能力要好一点,遇到问题的时候可以到用英文查资料;搜索问题答案的能力强一点,因为很多时候别人没空教你;打字的能力强一点,至少不用二龙戏珠那么痛苦。
面试其实有点像谈恋爱,面试官的主观好恶有很大成份在里面;不过就像漂亮女生人人爱一样,达到80%的程序员,我想大部份人还是会喜欢上的。
作者 Michael Livshitz 2007年7月3日
BackgroundWorker可以让窗体异步地完成一个操作。在我们需要执行诸如『数据库事务』或者『图片下载』之类的操作时,这个功能非常有 用。此时,我们的可以让用户界面停止响应(或者隐藏起来直到操作结束)。在这篇文章中,我会一步一步教会你如何在.NET 2.0程序中使用BackgroundWorker组件以便处理较耗时的操作。示例程序使用C#编写。
与往常一样,我们创建一个测试工程,取名为"TestBGW",使之只包含一个窗体("FormBGW"):
图1.
我们将使用BackgroundWorker完成一些数据库的事务操作(比如,获取一些DataTable)。首先拖一个BackgroundWorker组件到我们窗体上。
图2.
我们将用DataTable来设置DataGridView1的DataSource属性。我们还应该刷新我们的用户界面,并告诉用户:所有的操作已经全部“OK”,他/她不用再操心啦。因此,我们还要需要一个StatusStrip和一个Timer.
图3.
为了让用户看到我们的处理过程正在运行之中,我们将用到toolStripProgressBar1:
图4.
用toolStripStatusLabel1和toolStripStatusLabelTime是来向用户显示处理过程的状态和已经花费的时间。
我们窗体看上去是这样子的:
图5.
为了模拟数据库的事务操作,我们将用到 GetData.dll(当然你也可以连接到一个真实的数据库;这个模拟的目的只是为了测试而已)。出于这个目的,我们把GetData.dll添加到引用中,然后写因getDataTable方法:
private DataTable getDataTable(int Rows)
{
GetData.GetDataHelp getData = new GetData.GetDataHelp();
return (getData.getDataSetCities(Rows).Tables[0]);
}
我们调用RunWokerAsync方法开始我们的异步操作:
private void FormBGW_Activated(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
BackGroundWorker组件有三个事件:
图6.
DoWork事件发生在RunWokerAsync方法被调用时。在这个事件的处理函数中,我们“完成”那些的耗时的工作(我们载入至少100000行数据以便使我们的处理过程变得“耗时”),并通知用户载入工作正在进行中,最后将我们的DataTable置为我们的异步操作的结果。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { DataTable dt; toolStripStatusLabel1.Text = "Loading ... " + "Thanks for your patience"; dt = getDataTable(1000000); e.Result = dt; }
if (toolStripProgressBar1.Value == toolStripProgressBar1.Maximum)
{
toolStripProgressBar1.Value = 0;
}
string sTime =" ..." + ts.Minutes.ToString("00") +
":" + ts.Seconds.ToString("00") +
":" + ts.Milliseconds.ToString("000");
toolStripStatusLabelTime.Text = sTime;
顺便说一句,如果仅仅为了测试ReportProgress如何工作,你可以给backgroundWorker1_DoWork方法加上下面的代码:
//-------to try percentage ...
int iMax = 100000;
for (int i = 0; i < iMax; i++)
{
backgroundWorker1.ReportProgress((i * 100) / (iMax - 1));
}
private void backgroundWorker1_ProgressChanged(object sender,ProgressChangedEventArgs e)
{
//-------to try percentage ...
toolStripProgressBar1.Value = e.ProgressPercentage;
toolStripStatusLabel1.Text = "Loading ... " +
e.ProgressPercentage.ToString() + "%";
//-------------------------
}
dataGridViewCities.DataSource = e.Result;
FormBGW.cs的全部代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace TestBGW
{
public partial class FormBGW : Form
{
public FormBGW()
{
InitializeComponent();
////to try percentage ...
//backgroundWorker1.WorkerReportsProgress = true;
}
#region "forClass"
DateTime startDate = DateTime.Now;
#endregion
private void FormBGW_Activated(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
timer1.Start();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
DataTable dt;
toolStripStatusLabel1.Text = "Loading ... " +
"Thanks for your patience";
dt = getDataTable(1000000);
////-------to try percentage ...
//int iMax = 100000;
//for (int i = 0; i < iMax; i++)
//{
// backgroundWorker1.ReportProgress
// ((i * 100) / (iMax - 1));
//}
////-------------------------
e.Result = dt;
toolStripStatusLabel1.Text = "Please, wait ...";
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
////-------to try percentage ...
//toolStripProgressBar1.Value = e.ProgressPercentage;
//toolStripStatusLabel1.Text = "Loading ... " +
// e.ProgressPercentage.ToString() + "%";
////-------------------------
}
private void backgroundWorker1_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
{
toolStripProgressBar1.Value = 100;
dataGridViewCities.DataSource = e.Result;
toolStripStatusLabel1.Text = "";
toolStripProgressBar1.Value = 0;
timer1.Stop();
toolStripStatusLabelTime.Text = "";
}
private DataTable getDataTable(int Rows)
{
GetData.GetDataHelp getData = new GetData.GetDataHelp();
return (getData.getDataSetCities(Rows).Tables[0]);
}
private void timer1_Tick(object sender, EventArgs e)
{
TimeSpan ts = DateTime.Now.Subtract(startDate);
string sTime =" ..." + ts.Minutes.ToString("00") +
":" + ts.Seconds.ToString("00") +
":" + ts.Milliseconds.ToString("000");
toolStripStatusLabelTime.Text = sTime;
if (toolStripProgressBar1.Value ==
toolStripProgressBar1.Maximum)
{
toolStripProgressBar1.Value = 0;
}
toolStripProgressBar1.PerformStep();
}
}
}
现在,如果我们运行我们的工程,我们会看到:
图7.
加载结束之后:
图8.
结论
我希望这篇文中可以帮助你在你的.NET 2.0程序中使用BakcgroundWorker组件以便执行一些耗时的操作。
祝好运与编程同在!
--------------
译者的话,这是我在译言翻译的第一篇。从我的角度讲,我是不赞同一个看不懂这篇文章原文的人做程序员的。不过我天生不爱放弃,既然接下了翻译任务,就完成了它吧。
作者超喜欢用we/our,我酌情删去了一些,不过还是有太多的“我们”。
