先说明一下我的功能要求(asp.net):要实现收邮件的功能,能让用户了解当前接收进度或情况。
现在我的设计思路是这样的,进入接收页面后,创建一个接收邮件的线程。定义一个事件代理,在执行到某个步骤时执行代理,这个代理是异步调用的(在主线程执行,这样才能使用Response,Request)。现在有点不解的是,在这个事件函数执行时只要执行到Response.Write()或它的其它方法时就停止执行了,它就认为异步调用已经完成了。下面给出大致代码:
//
// 创建一个线程
//
Thread m_receiveThread = new Thread(new ThreadStart(ReceiveThread));
Session["Thread"] = m_receiveThread;
m_receiveThread.Start();
m_receiveThread.Priority = ThreadPriority.Lowest;//
// 线程函数体
//
private void ReceiveThread()
{
//
// 接收邮件类
//
ReceiveMailBus m_receiver = new ReceiveMailBus(Att_EmailAccounts,Att_CurrentEmailAccountId,m_resetEvent);
//
// 事件关联
//
m_receiver.OnReceive += new ReceiveEventHander(this.OnReceive);
int m_intReceiveCount = m_receiver.Receive(Att_MessageId,Att_EmailList);
}
/// 连接
public bool Connect()
{
if(OnReceive != null)
{
//就是这边进行异步调用,为的就是让这个函数能在主线程中执行
IAsyncResult m_ar = OnReceive.BeginInvoke(this,new ReceiveEventArgs(STR_ONCONNECT,true,false),null,null);
bool m_b = m_ar.IsCompleted;//调用完这里的值是true
if(m_b)
OnReceive.EndInvoke(m_ar);
}
try
{
string m_strPOP3 = m_EmailSetupRow[EmailAccountData.STR_POP3_FIELD].ToString();
m_pop3.Connect(m_EmailSetupRow[EmailAccountData.STR_LOGINNAME_FIELD].ToString(),m_strPwd,m_strPOP3,m_intPop3Port);
}
catch(Exception exp)
{
if(OnReceive != null)
OnReceive(this,new ReceiveEventArgs(STR_CONNECT_ERR + ":" + exp.Message,false,true));
throw new CustomException(STR_CONNECT_ERR+ ":" + exp.Message,exp);
}
if(OnReceive != null)
{
IAsyncResult m_ar = OnReceive.BeginInvoke(this,new ReceiveEventArgs(STR_ONCONNECT,true,false),null,null);
}
}
private void OnReceive(object sender,ReceiveEventArgs e)
{
//
// 孟子老大那借来的代码,假的进度显示
//
Response.Write("<script>mydiv.innerText = '22222';</script>"); //事件执行到这句,函就算结束了,下面的语句都不执行了。但如果这前面有其它语句,不是Response物件的,都能执行,但是不管怎么样,一执行到Response这里就退出了。
Response.Write("<script language=javascript>;");
Response.Write("var dots = 0;var dotmax = 10;function ShowWait()");
Response.Write("{var output; output = '" + e.Att_strMessage + "';dots++;if(dots>=dotmax)dots=1;");
Response.Write("for(var x = 0;x < dots;x++){output += '·';}mydiv.innerText = output;}");
Response.Write("function StartShowWait(){mydiv.style.visibility = 'visible'; ");
Response.Write("window.setInterval('ShowWait()',1000);}");
Response.Write("function HideWait(){mydiv.style.visibility = 'hidden';");
Response.Write("window.clearInterval();}");
Response.Write("StartShowWait();</script>");
Response.Flush();
}为了能让你看清楚,特意排了一下。能理解我的意思吗?再说一遍我的目的,工作线程的进度在主线程体现出来。试过AutoResetEvent进行同步控制,但考虑到不能让主线程处于等待状态,(因为要等待工作线程的工作,这样就不接受客户的请求).
现在我的设计思路是这样的,进入接收页面后,创建一个接收邮件的线程。定义一个事件代理,在执行到某个步骤时执行代理,这个代理是异步调用的(在主线程执行,这样才能使用Response,Request)。现在有点不解的是,在这个事件函数执行时只要执行到Response.Write()或它的其它方法时就停止执行了,它就认为异步调用已经完成了。下面给出大致代码:
//
// 创建一个线程
//
Thread m_receiveThread = new Thread(new ThreadStart(ReceiveThread));
Session["Thread"] = m_receiveThread;
m_receiveThread.Start();
m_receiveThread.Priority = ThreadPriority.Lowest;//
// 线程函数体
//
private void ReceiveThread()
{
//
// 接收邮件类
//
ReceiveMailBus m_receiver = new ReceiveMailBus(Att_EmailAccounts,Att_CurrentEmailAccountId,m_resetEvent);
//
// 事件关联
//
m_receiver.OnReceive += new ReceiveEventHander(this.OnReceive);
int m_intReceiveCount = m_receiver.Receive(Att_MessageId,Att_EmailList);
}
/// 连接
public bool Connect()
{
if(OnReceive != null)
{
//就是这边进行异步调用,为的就是让这个函数能在主线程中执行
IAsyncResult m_ar = OnReceive.BeginInvoke(this,new ReceiveEventArgs(STR_ONCONNECT,true,false),null,null);
bool m_b = m_ar.IsCompleted;//调用完这里的值是true
if(m_b)
OnReceive.EndInvoke(m_ar);
}
try
{
string m_strPOP3 = m_EmailSetupRow[EmailAccountData.STR_POP3_FIELD].ToString();
m_pop3.Connect(m_EmailSetupRow[EmailAccountData.STR_LOGINNAME_FIELD].ToString(),m_strPwd,m_strPOP3,m_intPop3Port);
}
catch(Exception exp)
{
if(OnReceive != null)
OnReceive(this,new ReceiveEventArgs(STR_CONNECT_ERR + ":" + exp.Message,false,true));
throw new CustomException(STR_CONNECT_ERR+ ":" + exp.Message,exp);
}
if(OnReceive != null)
{
IAsyncResult m_ar = OnReceive.BeginInvoke(this,new ReceiveEventArgs(STR_ONCONNECT,true,false),null,null);
}
}
private void OnReceive(object sender,ReceiveEventArgs e)
{
//
// 孟子老大那借来的代码,假的进度显示
//
Response.Write("<script>mydiv.innerText = '22222';</script>"); //事件执行到这句,函就算结束了,下面的语句都不执行了。但如果这前面有其它语句,不是Response物件的,都能执行,但是不管怎么样,一执行到Response这里就退出了。
Response.Write("<script language=javascript>;");
Response.Write("var dots = 0;var dotmax = 10;function ShowWait()");
Response.Write("{var output; output = '" + e.Att_strMessage + "';dots++;if(dots>=dotmax)dots=1;");
Response.Write("for(var x = 0;x < dots;x++){output += '·';}mydiv.innerText = output;}");
Response.Write("function StartShowWait(){mydiv.style.visibility = 'visible'; ");
Response.Write("window.setInterval('ShowWait()',1000);}");
Response.Write("function HideWait(){mydiv.style.visibility = 'hidden';");
Response.Write("window.clearInterval();}");
Response.Write("StartShowWait();</script>");
Response.Flush();
}为了能让你看清楚,特意排了一下。能理解我的意思吗?再说一遍我的目的,工作线程的进度在主线程体现出来。试过AutoResetEvent进行同步控制,但考虑到不能让主线程处于等待状态,(因为要等待工作线程的工作,这样就不接受客户的请求).
bool m_b = m_ar.IsCompleted;//调用完这里的值是true
if(m_b)
OnReceive.EndInvoke(m_ar);
}
由于是异步调用,所以bool m_b = m_ar.IsCompleted;这个语句会立刻执行,这句话应该放在异步事件里才对。
可是这个跟我的异步执行函数有什么关系呢,它只是判断异步函数是否已经执行结束了。可是如果在异步函数里没有执行Response的方法的话就能正常退出,如果有的话就执行到第一个Response的方法时函数就退出了,是Response这个物件的问题我想。