2017-10-02 4 views
0

電子メールを送信する特定のメソッドを持つWebサービス.Netコア2があります。私はsmtpclient.sendemailasyncを使ってうまく動作しています。.NetコアWebサービスを待たずに非同期電子メールを送信する

public async Task<bool> SendEmailAsync(MailMessage email) 
    { 
     try 
     { 
      if (string.IsNullOrWhiteSpace(emailFrom)) email.From = new MailAddress(emailFrom); 
      using (SmtpClient client = getSMTPClientInstance()) 
      { 
       await client.SendMailAsync(email); 

      } 
      return true; 
     } 
     catch (Exception ex) 
     { 
      Log.Error(ex, "Error sending email in EmailService.SendEmailAsync"); 
      return false; 
     } 
    } 

唯一の問題は、一部のSMTPサーバーが応答に時間がかかりすぎることです。私は電子メールを設定し、キューに入れて、結果を待たずに戻りたいと思う。

ただunawaited非同期を使用するのは2つの理由からです。

  1. 私が持っている私は、ログ

を書くために私のエンティティフレームワークのデータベースコンテキストにアクセスする必要がASPで要求コンテキスト外で

  • の方法を継続することが信頼できるものではありません(私のクライアントが指定する)外部または内部のSMTPを許可するので、コレクションフォルダは可能ではありません。少なくとも、それを管理するサービスがないわけではありません。

    これをどのように達成できますか?これを管理するサービスを書く必要がありますか?もしそうなら、どのように私は私のネットコアアプリケーションの内部で、サービスもログ

    UPDATE

    を書くためにEFコンテキストにアクセスする必要があることを念頭に置いては可能な配管が.NetCoreであることを行うだろう特にこれはDIです。以下の私の追加の答えを参照してください。 IServiceScopeFactoryを使用する

  • 答えて

    2

    PageオブジェクトでRegisterAsyncTaskメソッドを呼び出すことができます。それはあなたがこれらの要求コンテキストを終了する前に終了していることを確認したいASP.NETランタイムを通知します:

    例:

    public void Page_Load(object sender, EventArgs e) 
    { 
        RegisterAsyncTask(new PageAsyncTask(LoadSomeData)); 
    } 
    
    public async Task LoadSomeData() 
    { 
    
        var clientcontacts = Client.DownloadStringTaskAsync("api/contacts"); 
        var clienttemperature = Client.DownloadStringTaskAsync("api/temperature"); 
        var clientlocation = Client.DownloadStringTaskAsync("api/location"); 
    
        await Task.WhenAll(clientcontacts, clienttemperature, clientlocation); 
    
        var contacts = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Contact>>(await clientcontacts); 
        var location = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await clientlocation); 
        var temperature = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await clienttemperature); 
    
        listcontacts.DataSource = contacts; 
        listcontacts.DataBind(); 
        Temparature.Text = temperature; 
        Location.Text = location; 
    } 
    

    https://www.hanselman.com/blog/TheMagicOfUsingAsynchronousMethodsInASPNET45PlusAnImportantGotcha.aspx

    0

    をので、私はそこに、答えをマークしている間、私の具体例のためのより良い解決策である2つの選択肢です。まずタスクをスケジューリングするためにハングファイアのようなライブラリを使用するという選択肢がありますが、これは技術的に質問に対する答えではありません。

    .NETコアでより良い解決策は、要求が完了したときに、それはスコープの外に行くdoes notのように、タスクをrescopeできIServiceScopeFactoryでIServiceScopeFactory

    を使用することです。私はコントローラで直接以下のことを行いました(後でハングファイアのアプローチを使用するようになりましたが、これはうまくいきます)。ご覧のように、非同期タスクは、コントローラーコードが続行されている間に、新しいunwaitedスレッドで強制終了されます。

     var task = Task.Run(async() => 
         { 
          using (var scope = _serviceScopeFactory.CreateScope()) 
          { 
           var service = scope.ServiceProvider.GetRequiredService<ApprovalService>(); 
           await service.sendResponseEmailAsync(approvalInfo.ApprovalId, userID, approvalInfo.emailTo, approvalInfo.ccTo); 
          } 
         }); 
    
    関連する問題