很久没写博客了,最近没有什么惊天地、泣鬼神的大作,就从小处着眼,总结一些开发过程中的一些心得和见解吧。

众所周知,互联网改变生活,现在是验证码大行其道的年代,基本上主要涉及用户信息注册、登录、提交数据等,都来一个验证码来限制下,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#内置的后台线程也是可以处理这个问题的,只是这个封装的后台线程,提供较好的一些封装及处理,可以应付更为复杂的情况,而对于要等线程返回值、用户可取消的操作,更是方便。系统这些对你有帮助!

标签: none

添加新评论