Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#:如何使用线程并知道线程工作何时完成?_C#_Multithreading_Threadpool - Fatal编程技术网

C#:如何使用线程并知道线程工作何时完成?

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

我在我的C#win表单项目中阅读了这封看不见的电子邮件。有些时候会有附件,下载时会产生这些附件,因此我的项目的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();
            }

        }));
    });
如果我删除线程池,它将很好地工作。 我使用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));
}