簡體   English   中英

理解等待或超時:如何同時發送多封郵件而不阻塞程序的rest

[英]Understanding the await or timeout: How to send multiple emails concurrently without blocking the rest of the program

這種並行編碼的新手。

我正在嘗試啟動任務列表(在這種情況下是要發送的電子郵件)。

下面的代碼確實有效,但是我不確定,如果一個 email 發送失敗,或者該任務由於任何原因無法完成等。

我的代碼會掛在await線上嗎?

這里有什么解決方案,還是沒有問題?

我需要根據需要等待或攔截每一個(將 email 標記為正確發送或重試等)。

但是正在等待一切安全,還是我應該有一個事件來攔截響應?
(我不在乎奇數是否需要一段時間,我的關鍵是不要阻塞程序的rest)

總而言之,這將是一個 5 分鍾的循環,我不希望 email 將來被阻塞是每個任務的超時,作為選項。

任何幫助都會很棒,謝謝。

// Create a list of emails to send
List<Task<string>> tasks = new List<Task<string>>();
foreach (var item in lstEmailList) // loop the list of emails to send
{
    tasks.Add(EmailLib.SendEmailOldSmtpAuth(item)); // add each email as a task
}

// now run the list as parallel tasks 
await Task.Run(() => Parallel.ForEach(tasks, s =>
{
    //EmailLib.SendEmailOldSmtpAuth(item);
}));

foreach (var task in tasks)
{
    var result = ((Task<string>)task).Result;
                        
    if (result.Contains("PH_OK") == true)
    {
        string strFindId = result.Replace("PH_OK=", "").ToString();
        int EmailID = Int32.Parse(strFindId);
        DbFunc.MarkEmailAsSent(ref SQLConnX, EmailID);
    }       
}

如果有幫助:

public async Task<string> SendEmailOldSmtpAuth(Data_PendingEmails objEmail)
{
    try
    {
        var emailMessage = new MimeMessage();

        string SendToName = "";

        if (objEmail.CarerID > 0)
        {
            SendToName = objEmail.carForename + " " + objEmail.carSurname;
        }
        else
        {
            SendToName = objEmail.cliForename + " " + objEmail.cliSurname;
        }

        if (SendToName == "")
        {
            SendToName = "User";
        }

        emailMessage.From.Add(new MailboxAddress(objEmail.EMailYourName, objEmail.EMailAddress));
        emailMessage.To.Add(new MailboxAddress(SendToName, objEmail.ToEmailAddress));
        emailMessage.Subject = objEmail.EmailSubject;
        emailMessage.Body = new TextPart("html") { Text = objEmail.EmailMessage };
        try
        {
            var client = new SmtpClient();

            await client.ConnectAsync(objEmail.SMTPServer, Int32.Parse(objEmail.SMTPPort), SecureSocketOptions.SslOnConnect);
            await client.AuthenticateAsync(objEmail.SMTPUserName, objEmail.SMTPPassword);

            await client.SendAsync(emailMessage);
            await client.DisconnectAsync(true);

            return "PH_OK=" + objEmail.EmailID.ToString();
        }
        catch (Exception ex)
        {
            var e = ex;

            return e.Message;
        }
    }
    catch (Exception SendEmailOldSmtpAuthOverAll) 
    {
        return SendEmailOldSmtpAuthOverAll.Message.ToString();
    }
}

我將嘗試用一個更簡單的示例來模擬您的場景,但主要思想是相同的。 我這樣做是為了模擬潛在的異常。

首先,您需要同時調用 web 服務,所以最好的方法是使用Task.WhenAll因為這是一個 I/O 操作(正如@Charlieface 已經提到的)

假設我們有一個電子郵件列表:

var emailList = new List<string>() { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14" };

然后我們需要創建一個可枚舉的任務:

var tasks = emailList.Select(async email =>
{
    var response = await SendEmailAsync(email);
    Console.WriteLine(response);
});

然后我們“模擬”一個異常並將 append 它放到任務列表中以模擬異常:

var problematicTask = ThrowExceptionAsync("Error from initial task");
var allTasks = tasks.Append(problematicTask);

現在,為了觸發任務並捕獲異常,我們需要這樣做:

var aggregateTasks = Task.WhenAll(allTasks);
try
{
    await aggregateTasks;
}
catch
{
    AggregateException aggregateException = aggregateTasks.Exception!;
    foreach (var ex in aggregateException.InnerExceptions)
    {
        Console.WriteLine(ex.Message);
    }
}

作為這個例子的輔助方法,我創建了這兩個任意方法:

async Task<string> SendEmailAsync(string email)
{
    await Task.Delay(1500);
    if (email.Equals("7") || email.Equals("10"))
    {
        await ThrowExceptionAsync("Error from sendEmail");
    }
    return $"Email: {email} sent";
}

async Task ThrowExceptionAsync(string msg)
{
    throw new Exception(msg);
}

如果您運行這個簡單的示例,您將檢查每次調用中可能引發的所有異常。

現在關於您的特定示例,我認為您需要刪除所有 try/catch 塊,以便將異常捕獲為聚合異常而不阻塞您的應用程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM