2016-08-22 18 views
-2

メールを非同期で送信する必要があります。私はかみそりビューからHTMLテンプレートを生成するためにRazor Generatorを使用することにしました。今私はメールとしてHTMLを送信するためにSmtpClient.SendMailAsyncを使用する必要があります。しかし、私は剃刀ジェネレータがかなりの時間がかかることがわかりました。私はsendmailメソッドがHtmlテンプレートを取得することについて心配すべきではないので、私はテンプレート生成部を私のsend mailメソッドの中に含めたくありません。Task.Run内で非同期メソッドを呼び出す方法は?

public static void SendEmailAsync<TModel>(TModel model, string templatePath, string subj, string toEmail, string cc = null, string bcc = null) 
    { 

     string templateFilePath = HostingEnvironment.MapPath(templatePath); 
     // Generate the email body from the template file. 
     // 'templateFilePath' should contain the absolute path of your template file. 
     if (templateFilePath != null) 
     { 
      Task.Run(() => 
      { 
       var emailHtmlBody = Engine.Razor.RunCompile(File.ReadAllText(templateFilePath), 
       templateFilePath, model.GetType(), model); 
       SendEmailAsync(subj, emailHtmlBody, toEmail, cc, bcc); 
      }); 
     } 
     else 
     { 
      throw new System.Exception("Could not find mail template."); 
     } 
    } 

とSendMailAsyncのための署名である:

私は、サンプルコードを持って

static async Task SendEmailAsync(string subj, string message, string toEmail, string cc = null, string bcc = null) 
    { 
     //Reading sender Email credential from web.config file 
     string fromEmail = ConfigurationManager.AppSettings["FromEmail"].ToString(); 
     string fromName = ConfigurationManager.AppSettings["FromName"].ToString(); 

     //creating the object of MailMessage 
     MailMessage mailMessage = new MailMessage(); 
     mailMessage.From = new MailAddress(fromEmail, fromName); //From Email Id 
     mailMessage.Subject = subj; //Subject of Email 
     mailMessage.Body = message; //body or message of Email 
     mailMessage.IsBodyHtml = true; 

     string[] toMuliId = toEmail.Split(','); 
     foreach (string toEMailId in toMuliId) 
     { 
      mailMessage.To.Add(new MailAddress(toEMailId)); //adding multiple TO Email Id 
     } 


     if (cc != null) 
     { 
      string[] ccId = cc.Split(','); 

      foreach (string ccEmail in ccId) 
      { 
       mailMessage.CC.Add(new MailAddress(ccEmail)); //Adding Multiple CC email Id 
      } 
     } 

     if (bcc != null) 
     { 
      string[] bccid = bcc.Split(','); 

      foreach (string bccEmailId in bccid) 
      { 
       mailMessage.Bcc.Add(new MailAddress(bccEmailId)); //Adding Multiple BCC email Id 
      } 
     } 

     SmtpClient smtp = new SmtpClient 
     { 
      EnableSsl = true, 
      Credentials = new NetworkCredential("", "") 
     }; 

     //network and security related credentials 
     await smtp.SendMailAsync(mailMessage); //sending Email 
    } 

んが、例外がスローされませんが、私はエラーを取得:

System.InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.

+0

基本的な問題は、あなたの 'st atic void SendEmailAsync (...) 'メソッドは' static async Task SendEmailAsync (...) 'でなければなりません。これで、 'Task.Run()'を '待つ'ことができます。これは、マークされた重複を含む以前に尋ねられた多くの質問で説明したのとまったく同じ問題です。 –

+0

@PeterDunihoコントローラまですべてのメソッドにasyncキーワードを追加し続けたくないだけです。 –

+0

@Aronありがとう、私はそれが同じ問題だと思う。 –

答えて

0

これを使用:

await Task.Run(async() => 
{ 
    await DoAsyncMethodAsync(); 
}); 
+0

また、 'DoAsyncMethodAsync()'を返すこともできます。 – Aron

+0

@Aron、 'あなたはTask.Run(DoAsyncMethodAsync())'を待っているのですか? –

+0

@MikeHenryいいえ私はしません。私は 'あなたがTask.Run(DoMethodAsync)'を待っていると思います。 – Aron

0

この問題はあるが電子メールが送信されるたびに次のメソッドを実行していることを確認します(これにより、それがエラーをスローした場合の時間)理想的

Engine.Razor.RunCompile 

、あなたはその後、キャッシュ

でテンプレートマネージャを使用して this articleを参照してください RunCompile

Engine.Razor.Run 

呼び出し、だけにして、次のメソッドを呼び出して、しなければなりません

+1

理想的には、コンパイル時にRazorをプリコンパイルします。> _ < – Aron

+0

私はいつも必要に応じてテンプレートを読み込みませんでした。テンプレートディレクトリに対してファイルウォッチャを実行します。プロジェクトを再コンパイルすることを心配する必要はありません:) – timkly

関連する問題