C#:如何使用线程并知道线程工作何时完成?
我在我的C#win表单项目中阅读了这封看不见的电子邮件。有些时候会有附件,下载时会产生这些附件,因此我的项目的UI在下载完成时会锁定。我正在使用ThreadPool来解决这个问题 这是我的密码:C#:如何使用线程并知道线程工作何时完成?,c#,multithreading,threadpool,C#,Multithreading,Threadpool,我在我的C#win表单项目中阅读了这封看不见的电子邮件。有些时候会有附件,下载时会产生这些附件,因此我的项目的UI在下载完成时会锁定。我正在使用ThreadPool来解决这个问题 这是我的密码: System.Threading.ThreadPool.QueueUserWorkItem((o) => { for (int i = 0; i < lstEmailAddress.Count; i++) { Get(i
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();
}
}));
});
如果我删除线程池,它将很好地工作。
我使用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));
}
传递给Task.Run()方法的lambda表达式中的代码将在另一个线程上执行。创建并运行任务后,控制流将立即返回给调用者(在我们的例子中,最终返回到UI消息循环,该循环将继续处理其他事件)。
当任务完成时,一些“唤醒”消息被发送到应用程序的消息队列,当消息循环接收并处理此消息时,执行将继续在停止的位置执行。
在我们的例子中,当任务完成时,将从“wait task.Run()”调用()之后的下一行开始在主线程上继续执行。
因此,命令对象将被启用(它将被绑定到一个按钮,比如说“下载电子邮件”,因此该按钮也将被启用),并显示消息框,其中说明将下载多少电子邮件 正如您所见,代码非常干净,易于阅读和理解(一旦您了解了使用async/await关键字和Task类的基本知识)
(也请阅读我在上面对异常处理的评论)没有足够清醒,无法给出完整答案,但我建议放弃
线程
类,改用任务。您只需创建一个任务并使用其ContinueWith
属性指定任务完成时执行的操作:task t=task.Run(()=>DoWork()).ContinueWith(()=>afterworkOne())代码>(从VB.net自动翻译,希望正确)。或者您可以使用Async
和wait
在代码中等待任务完成,同时也不锁定UI。听起来您在第一个线程完成执行之前获取电子邮件。将作业添加到线程池的代码是什么样子的?没有足够的信息提供答案。例外情况发生在哪里?什么是完整的堆栈跟踪?什么原因导致操作启动?为什么操作(显然)在前一个操作完成之前再次启动?可以做其他事情来帮助改进上述代码,但首先需要解决您所询问的具体问题。请提供可靠的重现问题的信息。另请参见。不要只接受例外。非常简单地说,您可以这样做:捕获异常->您知道如何处理它以及如何修复这种情况吗?如果是->执行/修复。如果没有->记录异常(不要忘记记录异常堆栈跟踪和内部异常)。确保您的模块未处于半更改状态。如果是,则回滚状态更改。如果异常发生在低级别->最有可能的情况是,您需要重新显示它,并让高级代码决定要做什么。
The Read method cannot be called when another read operation is pending
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));
}