Ela*_*ahe 3 c# multithreading threadpool
我在C#win表单项目中阅读了UNSEEN电子邮件.有些时候有附加文件,下载有一些时间,所以我的项目的UI将在下载完成期间锁定.我使用ThreadPool来解决这个问题.
这是我的代码:
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();
}
}));
});
Run Code Online (Sandbox Code Playgroud)
这是我使用的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;
}
}
Run Code Online (Sandbox Code Playgroud)
正如你在上面的代码中看到的那样,我完全在线程工作完成时有一个动作.实际上,我想告知完成线程工作.
但问题出在这里:大多数时候,当我想从收件箱中获取邮件时,我遇到了这个例外.
The Read method cannot be called when another read operation is pending
Run Code Online (Sandbox Code Playgroud)
如果我删除将运行良好的线程池.我使用threadPool只是为了忽略UI锁定,也知道线程已完成.
有什么更好的方法可以建议我吗?谢谢你的帮助......
有什么更好的方法可以建议吗?
以下是我在WPF应用程序中以现代方式(不再是,如果你在2020年阅读)方法的方法:
private async void DoSomethingAsync()
{
try
{
DoanloadEmailsCommand.IsEnabled = false;
await Task.Run(() =>
{
// Do something here. For example, work with the database, download emails, etc.
Emails = DownloadEmails();
});
}
finally
{
DoanloadEmailsCommand.IsEnabled = true;
}
MessageBox.Show(string.Format("{0} emails have been downloaded.", Emails.Count));
}
Run Code Online (Sandbox Code Playgroud)
传递给Task.Run()方法的lambda表达式中的代码将在另一个线程上执行.
在创建和运行任务之后,控制流将直接返回给调用者(在我们的情况下最终返回到UI消息循环,这将继续处理其他事件).
当任务完成时,会向应用程序的消息队列发送一些"唤醒"消息,并且当消息循环接收并处理此消息时,执行将在停止的位置继续执行.
在我们的例子中,当任务完成时,将在"await Task.Run()"call()之后的下一行的主线程上继续执行.
因此命令对象将被启用(它将被绑定到一个按钮,让我们说"下载电子邮件",这样按钮也将被启用),并显示消息框,说明将下载多少封电子邮件.
正如您所看到的,代码非常干净且易于阅读和理解(一旦您了解了使用async/await关键字和Task类的基础知识).
(也请阅读上面关于异常处理的评论)
| 归档时间: |
|
| 查看次数: |
161 次 |
| 最近记录: |