2017-09-16 79 views
-1

我目前的程序有問題,我正在嘗試學習如何使用smtp發送電子郵件,並且我編寫了此代碼來執行此操作。當我嘗試點擊button1時,程序凍結而沒有任何反應。 PS:很明顯,在發佈之前,我已將電子郵件和密碼更改爲「電子郵件」和「密碼」。 PS2:我正在用葡萄牙語寫我的代碼,所以你可能不明白的任何東西只是作爲變量或「x」來考慮。試圖用smtp發送電子郵件時程序凍結

編輯:我用一個簡單的線解決了這個問題,程序中缺少一個端口,誰有同樣的問題只需添加smtp.Port = 587; 。下面

代碼:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Net.Mail; 
using MySql.Data.MySqlClient; 
using System.Net; 

namespace Inicio 
{ 
    public partial class Email : Form 
    { 
     MySqlConnection con = new MySqlConnection(@"Data Source=localhost;port=3306;Initial Catalog=digital wallet;User ID=root;password="); 
     public Email() 
     { 
      InitializeComponent(); 
     } 

     private void SendEmail() 
     { 

      if (textBox1.Text == "" || textBox2.Text == "") 
      { 
       MessageBox.Show("Preencha todos os campos", "Erro", 
       MessageBoxButtons.OK, MessageBoxIcon.Error); 
      } 
      else 
      { 
       int i = 0; 
       con.Open(); 
       MySqlCommand cmd = con.CreateCommand(); 
       cmd.CommandType = CommandType.Text; 
       cmd.CommandText = "select EMAIL from conta where EMAIL = @email and LOGIN = @login "; 
       cmd.Parameters.AddWithValue("@email", textBox2.Text); 
       cmd.Parameters.AddWithValue("@login", textBox1.Text); 
       cmd.ExecuteNonQuery(); 
       DataTable dt = new DataTable(); 
       MySqlDataAdapter da = new MySqlDataAdapter(cmd); 
       da.Fill(dt); 
       i = Convert.ToInt32(dt.Rows.Count.ToString()); 

       if (i == 0) 
       { 
        MessageBox.Show("Login ou email inválidos", "Erro", 
        MessageBoxButtons.OK, MessageBoxIcon.Error); 
       } 
       else 
       { 
        cmd.CommandText = "select * from CONTA where LOGIN = @login"; 
        cmd.ExecuteNonQuery(); 

        string senha = ""; 
        string email = ""; 

        MySqlDataReader reader = cmd.ExecuteReader(); 
        while (reader.Read()) 
        { 
         senha = reader.GetString("SENHA"); 
         email = reader.GetString("EMAIL"); 
        } 

        reader.Close(); 

        using (SmtpClient smtp = new SmtpClient()) 
        { 
         smtp.Host = "outlook.com"; 
         smtp.UseDefaultCredentials = false; 
         NetworkCredential netCred = new NetworkCredential("email", "password"); 
         smtp.Credentials = netCred; 
         smtp.EnableSsl = true; 

         using (MailMessage msg = new MailMessage("email", email)) 
         { 
          msg.Subject = "Recuperação de senha."; 
          StringBuilder sb = new StringBuilder(); 
          sb.AppendLine("A sua senha é atual é: " + senha + Environment.NewLine); 
          sb.AppendLine("Obrigado," + Environment.NewLine); 
          sb.AppendLine("Digital wallet. " + Environment.NewLine); 
          msg.Body = sb.ToString(); 
          msg.IsBodyHtml = false; 
          smtp.Send(msg); 
         } 
        } 
       } 
      } 
     } 
     private void button1_Click(object sender, EventArgs e) 
     { 
      SendEmail(); 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      this.Close(); 
     } 
    } 
} 

回答

0

您在GUI環境中運行。事件必須儘快返回,否則GUI將被「鎖定」。磁盤和網絡活動特別容易長時間運行。您必須應用某種形式的多任務(並將長時間運行的操作移至該備用任務中)以避免GUI鎖定。

作爲初學者,我建議使用BackgroundWorker進行多任務處理。異步...等待更先進。

編輯:這是我的WinForms + BackgroundWorker示例代碼。它應該有助於讓你開始正確使用它。

#region Primenumbers 
 
private void btnPrimStart_Click(object sender, EventArgs e) 
 
{ 
 
\t if (!bgwPrim.IsBusy) 
 
\t { 
 
\t \t //Prepare ProgressBar and Textbox 
 
\t \t int temp = (int)nudPrim.Value; 
 
\t \t pgbPrim.Maximum = temp; 
 
\t \t tbPrim.Text = ""; 
 

 
\t \t //Start processing 
 
\t \t bgwPrim.RunWorkerAsync(temp); 
 
\t } 
 
} 
 

 
private void btnPrimCancel_Click(object sender, EventArgs e) 
 
{ 
 
\t if (bgwPrim.IsBusy) 
 
\t { 
 
\t \t bgwPrim.CancelAsync(); 
 
\t } 
 
} 
 

 
private void bgwPrim_DoWork(object sender, DoWorkEventArgs e) 
 
{ 
 
\t int highestToCheck = (int)e.Argument; 
 
\t //Get a reference to the BackgroundWorker running this code 
 
\t //for Progress Updates and Cancelation checking 
 
\t BackgroundWorker thisWorker = (BackgroundWorker)sender; 
 

 
\t //Create the list that stores the results and is returned by DoWork 
 
\t List<int> Primes = new List<int>(); 
 
\t 
 

 
\t //Check all uneven numbers between 1 and whatever the user choose as upper limit 
 
\t for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2) 
 
\t { 
 
\t \t //Report progress 
 
\t \t thisWorker.ReportProgress(PrimeCandidate); 
 
\t \t bool isNoPrime = false; 
 

 
\t \t //Check if the Cancelation was requested during the last loop 
 
\t \t if (thisWorker.CancellationPending) 
 
\t \t { 
 
\t \t \t //Tell the Backgroundworker you are canceling and exit the for-loop 
 
\t \t \t e.Cancel = true; 
 
\t \t \t break; 
 
\t \t } 
 

 
\t \t //Determin if this is a Prime Number 
 
\t \t for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2) 
 
\t \t { 
 
\t \t \t if (PrimeCandidate % j == 0) 
 
\t \t \t \t isNoPrime = true; 
 
\t \t } 
 

 
\t \t if (!isNoPrime) 
 
\t \t \t Primes.Add(PrimeCandidate); 
 
\t } 
 

 
\t //Tell the progress bar you are finished 
 
\t thisWorker.ReportProgress(highestToCheck); 
 

 
\t //Save Return Value 
 
\t e.Result = Primes.ToArray(); 
 
} 
 

 
private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e) 
 
{ 
 
\t pgbPrim.Value = e.ProgressPercentage; 
 
} 
 

 
private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
 
{ 
 
\t pgbPrim.Value = pgbPrim.Maximum; 
 
\t this.Refresh(); 
 

 
\t if (!e.Cancelled && e.Error == null) 
 
\t { 
 
\t \t //Show the Result 
 
\t \t int[] Primes = (int[])e.Result; 
 

 
\t \t StringBuilder sbOutput = new StringBuilder(); 
 

 
\t \t foreach (int Prim in Primes) 
 
\t \t { 
 
\t \t \t sbOutput.Append(Prim.ToString() + Environment.NewLine); 
 
\t \t } 
 

 
\t \t tbPrim.Text = sbOutput.ToString(); 
 
\t } 
 
\t else 
 
\t { 
 
\t \t tbPrim.Text = "Operation canceled by user or Exception"; 
 
\t } 
 
} 
 
#endregion

+0

哦......看來,我有工作要做。 –

0

處理您的SQL查詢,連接到SMTP服務器和郵件數據transfering到服務器需要時間。既然你在UI-Thread中執行所有這些東西,你的表單就會凍結。

添加BackgroundWorker到您的窗體中添加事件處理程序.DoWork.RunWorkerCompleted並添加SQL和SMTP的東西到DoWork功能。

On Button1單擊開始使用.RunWorkerAsync的BackgroundWorker。使用TextBox1和TextBox2內容將字符串數組傳遞給此函數。您需要這樣做,因爲您無法訪問DoWork函數中的那些元素。或者,您可以使用.IsBusy檢查工作人員是否已處於活動狀態。啓動工作人員後,您應該鎖定UI或顯示一條消息或類似消息來告訴用戶後臺進程正在運行。從Button1Click函數中執行此操作。

然後修改.DoWork函數來提取傳遞的字符串數組。你通過訪問傳入的DoWorkEventArgs.Arguments並將它們轉換爲傳遞給RunWorkerAsync的類型來轉換爲字符串數組。將TextBox訪問交換到數組值。

RunWorkerCompleted函數中,您必須解鎖UI。

開始閱讀有關BackgroundWorker的,你可以使用報告進度功能,通知有關進展情況的用戶,像「收集SQL數據,連接到SMTP服務器,郵件transfering數據,做」 ...

+0

因此,代碼是正確的? –

+0

我離開程序運行,我收到一個說,操作時間限制超過excepction。 –

+0

操作超時時間表示網絡端出現問題。錯誤的證書或Protocoll。找不到服務器。類似的東西。您需要查看內部異常以確定究竟是什麼。像這樣進入某種超時狀態的風險是一直將網絡資料納入多任務處理的一個原因。 – Christopher

0

Luan Teixeira,

你應該看看Asynchronous Programming with Async and Await。這將解決你的問題。

演示我在說什麼。看看這個代碼。

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 
    private async Task SendEmail() 
    { 

     if (textBox1.Text == "" || textBox2.Text == "") 
     { 
      MessageBox.Show("Preencha todos os campos", "Erro", 
      MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 
     else 
     { 
      await Email.SendEmail(); 

      MessageBox.Show("Nice"); 
     } 
    } 
    private async void button1_Click(object sender, EventArgs e) 
    { 
     await SendEmail(); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     this.Close(); 
    } 
} 

public class Email 
{ 
    public async static Task SendEmail() 
    { 
     await Task.Delay(15000); 
    } 
} 

你可以在textbox1和textbox2中寫一些東西,然後點擊按鈕。等待15秒(我正在模擬一個非常艱鉅的任務,可能需要15秒)。同時你可以看到用戶界面不凍結。你可以移動窗口。 15秒後,您將收到「Nice」消息。

這是因爲在我的代碼中,巨大的任務沒有在GUI線程中運行。

希望它可以幫助 親切的問候 丹尼爾

+0

謝謝,我會看看這個。 –