从获取QQ验证码谈如何改进用户体验,提高程序的响应效果
很久没写博客了,最近没有什么惊天地、泣鬼神的大作,就从小处着眼,总结一些开发过程中的一些心得和见解吧。
众所周知,互联网改变生活,现在是验证码大行其道的年代,基本上主要涉及用户信息注册、登录、提交数据等,都来一个验证码来限制下,QQ在这方面可真是运用到了极致,因此做QQ的开发,必须了解如何处理验证码的问题。一般验证码是通过一个带参数的URL获取到一个数字字符图片,由于网络原因,一般返回比较缓慢,所以如果要提高用户体验和程序的响应速度,就必须采用改良一点的方法来进行处理。
我们先从一个正常的操作讲起,逐步改进,看看效果及使用情况,如一般的处理就是把它封装在一个独立的函数中,在触发事件的地方调用该函数,如下所示。
{
HttpHelper httpHelper = new HttpHelper();
using (Stream s = httpHelper.GetStream("http://ptlogin2.qq.com/getimage?aid=3000801&0.43878429697395826", Portal.gc.cookieQun))
{
if (s == null)
{
MessageUtil.ShowWarning("获取登陆码错误,请检查您的网络!");
return;
}
pictureBox1.Image = Image.FromStream(s);
}
}
这种方式方式是一般的处理方式,有时候界面会因为获取网络数据而有停顿,除非你的网络非常好,所以可以把它放到一个独立的线程中进行处理,通过hreadPool.QueueUserWorkItem来进行线程处理,如下代码所示:
{
ThreadPool.QueueUserWorkItem(GetNewImageThread, null);
}
private void GetNewImageThread(object obj)
{
using (Stream s = httpHelper.GetStream("https://mail.qq.com/cgi-bin/getverifyimage?aid=23000101&f=html&ck=1&31997", EmailCookie))
{
if (s == null)
{
SetTips("获取登陆码错误,请检查您的网络!");
return;
}
this.pictureBox1.Invoke(new MethodInvoker(delegate()
{
this.pictureBox1.Image = Image.FromStream(s);
}));
}
}
这样已经比较好的处理界面停顿等不友好的问题了,不过有时候,因为使用了Invoke函数,可能会出现一些线程间的异常,如你关闭了窗口,而进行还在运行,就会出现一些问题,但是还是相对比较好的解决途径。
偶尔一天,看到一个比较好的后台线程封装类QueuedBackgroundWorker,使用效果还比较不错,虽然代码多了一些,不过处理起来效果还真的不错,还支持取消线程操作等功能,整个后台线程以及获取验证码的操作代码如下所示,整个代码运行效果不错,而且不会出现线程间的绑定错误。
private QueuedBackgroundWorker worker;
public Form1()
{
InitializeComponent();
worker = new QueuedBackgroundWorker();
worker.IsBackground = true;
worker.Threads = 1;
worker.ProcessingMode = ProcessingMode.FIFO;
worker.DoWork += new QueuedWorkerDoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunQueuedWorkerCompletedEventHandler(worker_RunWorkerCompleted);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
worker.DoWork -= worker_DoWork;
worker.RunWorkerCompleted -= worker_RunWorkerCompleted;
worker.Dispose();
}
private void GetVerifyImage()
{
worker.RunWorkerAsync("GetImage");
}
void worker_DoWork(object sender, QueuedWorkerDoWorkEventArgs e)
{
string newverifyUrl = "http://captcha.qq.com/getimage?aid=1007901&0.5723910723542236";
string referer = "http://reg.qq.com";
cookieReg = new CookieContainer();
HttpHelper httpHelper = new HttpHelper();
using (Stream s = httpHelper.GetStream(newverifyUrl, cookieReg, referer))
{
if (s == null)
{
MessageUtil.ShowWarning("获取登陆码错误,请检查您的网络!");
return;
}
e.Result = Image.FromStream(s);
}
}
void worker_RunWorkerCompleted(object sender, QueuedWorkerCompletedEventArgs e)
{
Image image = e.Result as Image;
if (image != null)
{
this.pictureBox1.Image = image;
}
}
线程封装类的源码地址提供给大家下载:https://files.cnblogs.com/wuhuacong/QueuedBackgroundWorker.rar
其实用C#内置的后台线程也是可以处理这个问题的,只是这个封装的后台线程,提供较好的一些封装及处理,可以应付更为复杂的情况,而对于要等线程返回值、用户可取消的操作,更是方便。系统这些对你有帮助!
转载请注明出处:撰写人:伍华聪 http://www.iqidi.com