我怎么能等待一个线程完成运行?Thread.join让我的主线程没有响应?

时间:2022-07-06 20:41:32

I'm working on project which sends mails to multiple users using windows application,But what is happening is,when I use Thread.Join() Method it is making my Main UI non-responsive...... What I want is.... I want to run SMTPClienTSetting() method on seperate thread and want my Main UI to remain responsive for other work..I wnat to run this mail sending acvtivity at the background...Please suggest me using threading concept only.....

我正在研究使用Windows应用程序向多个用户发送邮件的项目,但是当我使用Thread.Join()方法时,它正在使我的主UI无响应......我想要的是....我想在单独的线程上运行SMTPClienTSetting()方法,并希望我的主UI保持对其他工作的响应。我想在后台运行此邮件发送活动...请建议我仅使用线程概念。 ....

public void SendMail(dataset ds)
        {
                           for(inti=0<ds.Tables[0].Rows.Count<i++)
                            {

                                Thread tMail = new Thread(() => {
                                     resValue = SMTPClienTSetting(ds, mail);

                                });
                                tMail.IsBackground = true;
                                tMail.Start();
                                tMail.Join();
                                if (resValue == "True")
                                {
                                   Thread tPopUp = new Thread(new ThreadStart(this.ShowMessagePopUp));
                                   tPopUp.IsBackground = true;
                                  this.BeginInvoke((MethodInvoker)delegate{
                            });
                                   tPopUp.Start();
                                   lblPOpUpInfo = "Message sent successfully to \nAsset Owner : " + AssetOwner + "\n" + "Email : " + RecipientID;

                                }
                                else
                                {
                                     Thread tPopUp = new Thread(new ThreadStart(this.ShowMessagePopUp));
                                     tPopUp.IsBackground = true;
                                                                 this.BeginInvoke((MethodInvoker)delegate{
                            });
                                     tPopUp.Start();
                                     lblPOpUpInfo = "Message sending failed to \nAsset Owner :" + AssetOwner + "\n" + "Email : " + RecipientID + "!!!\nPlease check your SMTP details and\nInternet Connection..!!!";
                                }
                         }
        }
        #region Function for setting SMTP Client
                public string SMTPClienTSetting(DataSet ds, MailMessage MailstoSend)
                {
                    try
                    {
                        SmtpClient objsmtp = new SmtpClient();
                        NetworkCredential NetAccess = new NetworkCredential();

                        NetAccess.UserName = ds.Tables[0].Rows[0][0].ToString();
                        //NetAccess.Password = base64Decode(ds.Tables[0].Rows[0][1].ToString());

                        NetAccess.Password = genFunc.base64Decode(ds.Tables[0].Rows[0][1].ToString());
                        objsmtp.Credentials = NetAccess;

                        objsmtp.Host = ds.Tables[0].Rows[0][2].ToString();
                        objsmtp.Port = Convert.ToInt16(ds.Tables[0].Rows[0][3].ToString());

                        objsmtp.Send(MailstoSend);

                        //System.Threading.Thread.Sleep(500);

                        return "True";
                    }
                    catch (NullReferenceException nr)
                    {
                        return nr.Message;
                    }
                    catch (Exception ex)
                    {
                        return ex.Message;
                    }
                }
                #endregion
        }

    #region Function to show Pop Up window using separate thread
    public void ShowMessagePopUp()
    {
           try
            {
                frmHomePopUp homePopUp = new frmHomePopUp();
                mailTimer.Elapsed += delegate { mailTimer.Stop(); homePopUp.Close(); };
                //mailTimer.Elapsed += this.TimeEvent;
                mailTimer.Interval=5000;
                mailTimer.Enabled = true;
                homePopUp.lblInfo.Text = lblPOpUpInfo;
                homePopUp.Refresh();
                mailTimer.Start();
                homePopUp.ShowDialog();

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

    }
    #endregion

    public  void mailTimer_Elapsed(object source, EventArgs e)
    {
        //frmHome home;
        mailTimer.Stop();
      }

1 个解决方案

#1


3  

Basically: don't use Thread.Join; what that does is block.

基本上:不要使用Thread.Join;那是做什么的阻止。

An appropriate approach would be to do any UI work at the end of the worker method:

一种合适的方法是在worker方法结束时执行任何UI工作:

Thread tMail = new Thread(() => {
     resValue = SMTPClienTSetting(ds, mail);

     if (resValue == "True") {
        // blah blah blah
     }
     // now: if you need to update any UI state:
     this.BeginInvoke((MethodInvoker)delegate {
        someControl.Text = lblPOpUpInfo; // for example
     });
});
tMail.IsBackground = true;
tMail.Start();

The call to Invoke / BeginInvoke switches back to the UI thread, essentially working as a callback.

对Invoke / BeginInvoke的调用切换回UI线程,基本上作为回调。

Note that you might also want to use ThreadPool rather than a Thread here.

请注意,您可能还希望在此处使用ThreadPool而不是Thread。

#1


3  

Basically: don't use Thread.Join; what that does is block.

基本上:不要使用Thread.Join;那是做什么的阻止。

An appropriate approach would be to do any UI work at the end of the worker method:

一种合适的方法是在worker方法结束时执行任何UI工作:

Thread tMail = new Thread(() => {
     resValue = SMTPClienTSetting(ds, mail);

     if (resValue == "True") {
        // blah blah blah
     }
     // now: if you need to update any UI state:
     this.BeginInvoke((MethodInvoker)delegate {
        someControl.Text = lblPOpUpInfo; // for example
     });
});
tMail.IsBackground = true;
tMail.Start();

The call to Invoke / BeginInvoke switches back to the UI thread, essentially working as a callback.

对Invoke / BeginInvoke的调用切换回UI线程,基本上作为回调。

Note that you might also want to use ThreadPool rather than a Thread here.

请注意,您可能还希望在此处使用ThreadPool而不是Thread。