我在我的C# Win Form项目中读取未读邮件。有时会附带一些文件,下载这些文件需要一些时间,因此在下载完成期间,我的项目UI将被锁定。为了解决这个问题,我使用线程池。
以下是我的代码:
System.Threading.ThreadPool.QueueUserWorkItem((o) =>
{
for (int i = 0; i < lstEmailAddress.Count; i++)
{
Get(imap[i], lstEmailAddress[i].MailBox, out Emails[i]);
}
this.BeginInvoke(new Action(() =>
{
for (int i = 0; i < lstEmailAddress.Count; i++)
{
for (int j = 0; j < Emails[i].Count; j++)
{
Database.EmailRecieve_Insert(Emails[i][j]);
}
arrEmailUserControl[i].txtRecievedCount.Text = (Convert.ToInt32(arrEmailUserControl[i].txtRecievedCount.Text) + Emails[i].Count).ToString();
}
}));
});
这是我使用的 Get 方法:
private bool Get(Imap4Client imap, string[,] MailBox, out List<EmailStruct> Emails)
{
Emails = new List<EmailStruct>();
try
{
for (int i = 0; i < MailBox.GetLength(0); i++)
{
Mailbox inbox = imap.SelectMailbox(MailBox[i, 1]);
int[] ids = inbox.Search("UNSEEN");
if (ids.Length > 0)
{
ActiveUp.Net.Mail.Message msg = null;
for (var j = 0; j < ids.Length; j++)
{
msg = inbox.Fetch.MessageObject(ids[j]);
EmailStruct email = new EmailStruct();
email.SourceAddress = msg.From.Email;
email.Subject = msg.Subject;
email.Text = msg.BodyText.Text.ToString();
msg.Attachments.StoreToFolder(InternalConstant.AttachmentFolder);
email.MailBoxID = Convert.ToInt32(MailBox[i, 0]);
Emails.Add(email);
}
}
}
return true;
}
catch (Exception)
{
return false;
}
}
如您在以上代码中所看到的,我有一个操作,正好在线程工作完成时运行。实际上,我想通知线程工作已经完成。
但是问题在于:大部分情况下,当我想要从收件箱中获取消息时,都会出现此异常。
The Read method cannot be called when another read operation is pending
如果我移除线程池,程序会正常运行。 我使用线程池只是为了避免UI锁定并知道线程何时完成。
你能否建议更好的方式? 感谢任何帮助...
Thread
类,改用Tasks
。你可以创建一个任务,并使用其ContinueWith
属性指定任务完成时执行的操作:Task t = Task.Run(() => DoWork()).ContinueWith(() => AfterWorkDone());
(从 VB.net 自动翻译,希望正确)。或者你可以使用Async
和Await
在代码中等待任务完成,而不会锁定用户界面。 - Jens