我目前的程序存在问题,我正在尝试学习如何使用smtp发送电子邮件,我写了这段代码来执行此操作。当我尝试点击button1时程序冻结,没有任何反应。 PS:显然我在发布之前将电子邮件和密码更改为“email”和“password”。 PS2:我用葡萄牙语编写我的代码,所以你可能不理解的任何东西都只考虑变量或“x”。
以下代码:
// *** Assign this to a variable (self)
var self = this;
that.window = $("#PenguinPopup");
that.window.kendoWindow({
width: "60%",
title: false,
visible: false,
resizable: false,
actions: [],
draggable: false,
modal: true,
open: function() {
$("html, body").css("overflow", "hidden");
that.isVisible = true;
$('.kPopUpTitle').html(values.title);
// *** use the self variable instead of this
self.sky.tigerStart();
答案 0 :(得分:0)
您正在GUI环境中运行。事件必须尽快返回,否则GUI将“锁定”。特别是磁盘和网络活动很容易长时间运行。您必须应用某种形式的多任务(并将长时间运行的操作移动到该备用任务中)以避免GUI锁定。
作为初学者,我建议使用BackgroundWorker进行多任务处理。异步...等待更先进。
编辑:这是我的WinForms + BackgroundWorker示例代码。它应该有助于您开始正确使用它。
#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
if (!bgwPrim.IsBusy)
{
//Prepare ProgressBar and Textbox
int temp = (int)nudPrim.Value;
pgbPrim.Maximum = temp;
tbPrim.Text = "";
//Start processing
bgwPrim.RunWorkerAsync(temp);
}
}
private void btnPrimCancel_Click(object sender, EventArgs e)
{
if (bgwPrim.IsBusy)
{
bgwPrim.CancelAsync();
}
}
private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
int highestToCheck = (int)e.Argument;
//Get a reference to the BackgroundWorker running this code
//for Progress Updates and Cancelation checking
BackgroundWorker thisWorker = (BackgroundWorker)sender;
//Create the list that stores the results and is returned by DoWork
List<int> Primes = new List<int>();
//Check all uneven numbers between 1 and whatever the user choose as upper limit
for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
{
//Report progress
thisWorker.ReportProgress(PrimeCandidate);
bool isNoPrime = false;
//Check if the Cancelation was requested during the last loop
if (thisWorker.CancellationPending)
{
//Tell the Backgroundworker you are canceling and exit the for-loop
e.Cancel = true;
break;
}
//Determin if this is a Prime Number
for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
{
if (PrimeCandidate % j == 0)
isNoPrime = true;
}
if (!isNoPrime)
Primes.Add(PrimeCandidate);
}
//Tell the progress bar you are finished
thisWorker.ReportProgress(highestToCheck);
//Save Return Value
e.Result = Primes.ToArray();
}
private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pgbPrim.Value = e.ProgressPercentage;
}
private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pgbPrim.Value = pgbPrim.Maximum;
this.Refresh();
if (!e.Cancelled && e.Error == null)
{
//Show the Result
int[] Primes = (int[])e.Result;
StringBuilder sbOutput = new StringBuilder();
foreach (int Prim in Primes)
{
sbOutput.Append(Prim.ToString() + Environment.NewLine);
}
tbPrim.Text = sbOutput.ToString();
}
else
{
tbPrim.Text = "Operation canceled by user or Exception";
}
}
#endregion
答案 1 :(得分:0)
处理你的sql-query,连接到smtp-server并将邮件数据传输到服务器需要时间。由于您在UI-Thread中执行了所有这些操作,因此表单会冻结。
在表单中添加BackgroundWorker
,添加.DoWork
和.RunWorkerCompleted
的事件处理程序,并将SQL和SMTP内容添加到DoWork
函数中。
在Button1上单击,使用.RunWorkerAsync
启动BackgroundWorker。使用TextBox1和TextBox2内容将字符串数组传递给此函数。您需要这样做,因为您无法从DoWork
函数访问这些元素。您可以选择使用.IsBusy
检查工作人员是否已处于活动状态。启动工作程序后,您应该锁定UI或显示消息或类似的信息,以告诉用户后台进程正在运行。从Button1Click函数执行此操作。
然后修改.DoWork
函数以提取传递的字符串数组。您可以通过访问传递的DoWorkEventArgs.Arguments
并将它们转换为传递给RunWorkerAsync
的类型 - 到字符串数组来实现。将TextBox访问权交换为数组值。
在RunWorkerCompleted
功能中,您必须解锁用户界面。
开始阅读有关BackgroundWorker的内容,您可以使用进度报告功能向用户通知进度,例如“收集sql数据,连接到smtp服务器,传输邮件数据,完成”......
答案 2 :(得分: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秒后,您将收到“好消息”。
那是因为在我的代码中,巨大的任务没有在GUI线程中运行。
希望它有所帮助 亲切的问候 丹尼尔
答案 3 :(得分:-1)
更改超时属性。因此,smtp.Timeout = 0;应该可以!