从获取QQ验证码谈如何改进用户体验,提高程序的响应效果
很久没写博客了,最近没有什么惊天地、泣鬼神的大作,就从小处着眼,总结一些开发过程中的一些心得和见解吧。
众所周知,互联网改变生活,现在是验证码大行其道的年代,基本上主要涉及用户信息注册、登录、提交数据等,都来一个验证码来限制下,QQ在这方面可真是运用到了极致,因此做QQ的开发,必须了解如何处理验证码的问题。一般验证码是通过一个带参数的URL获取到一个数字字符图片,由于网络原因,一般返回比较缓慢,所以如果要提高用户体验和程序的响应速度,就必须采用改良一点的方法来进行处理。
我们先从一个正常的操作讲起,逐步改进,看看效果及使用情况,如一般的处理就是把它封装在一个独立的函数中,在触发事件的地方调用该函数,如下所示。
public
void
GetNewImage()
{
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来进行线程处理,如下代码所示:
public
void
GetNewImage()
{
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#内置的后台线程也是可以处理这个问题的,只是这个封装的后台线程,提供较好的一些封装及处理,可以应付更为复杂的情况,而对于要等线程返回值、用户可取消的操作,更是方便。系统这些对你有帮助!