简体   繁体   English

在同步调用方法中调用异步等待方法

[英]Call async await method in sync calling method

This is only the idea on what im doing in a window service. 这只是在窗口服务中即时通讯的想法。 I get the idea from this video to do it in parallel processing. 我从这段视频中得到了实现并行处理的想法。

I have two different method and a model class. 我有两个不同的方法和一个模型类。

Model Class code: 型号分类代码:

public class Email(){
    public string Recipient { get; set; }
    public string Message { get; set; }
}

Methods is something like this: 方法是这样的:

public void LoadData(){
    while(Main.IsProcessRunning){
        // 1. Get All Emails
        var emails = new dummyRepositories().GetAllEmails(); //This will return List<Emails>.
        // 2. Send it
        // After sending assume that the data will move to other table so it will not be query again for the next loop.
        SendDataParallel(emails);//this will function async? even though the calling method is sync.

        // This will continue here or wait until it already send?
        // If it will continue here even though it will not send already
        // So there's a chance to get the email again for the next loop and send it again?
    }
}

//This will send email at parallel
public async void SendDataParallel(IList<Email> emails){
    var allTasks = emails.Select(SendDataAsync);
    await TaskEx.WhenAll(allTasks);
}

//Assume this code will send email asynchronously. (this will not send email, for sample only)
public async void SendDataAsync(Email email){
    using (var client = new HttpClient())
    {
        client.PostAsync(email);
    }
}

I only want to get all queued emails then send it in parallel then wait until it already send. 我只想获取所有排队的电子邮件,然后并行发送,然后等待直到它已经发送。 I'm avoiding using foreach on every email that I get. 我避免在收到的每封电子邮件上使用foreach

Doesn't your compiler highlight your code with errors? 您的编译器是否不以错误突出显示您的代码?

If you mark your method as async while it doesn't return any value, you should set your return type as Task, not void: 如果在不返回任何值的情况下将方法标记为异步,则应将返回类型设置为Task而不是void:

public async Task SendDataParallel(IList<Email> emails){
    var allTasks = emails.Select(SendDataAsync);
    await Task.WhenAll(allTasks);
}

Your second method also shoud return a Task, otherwise what you want to (a)wait in the first method? 您的第二个方法也应该返回一个Task,否则您想要(a)在第一个方法中等待什么?

public async Task SendDataAsync(Email email){
    using (var client = new HttpClient())
    {
        return client.PostAsync(email);
    }
}

Now you can Select all your SendDataAsync tasks in SendDataParallel and .Wait() it's task in LoadData in synchronious mode: 现在,您可以在SendDataParallel和.Wait()中选择所有SendDataAsync任务,这是在LoadData中以同步模式执行的任务:

public void LoadData(){
    while(Main.IsProcessRunning){
        var emails = new dummyRepositories().GetAllEmails(); //This will return List<Emails>.
        SendDataParallel(emails).Wait();
    }
}

More information you can find reading answers in other SO questions and docs on MSDN: 您可以在MSDN上的其他SO问题和文档中找到更多信息的阅读答案:

And as you used LINQ's Select() which is based on foreach cycle next article also could be useful: Nested task inside loop 当您使用基于foreach周期的LINQ的Select()时,下一篇文章也可能会有用: 循环内嵌套任务

Lets start at the bottom: 让我们从底部开始:

  1. You dispose your client before you actually finish receiving the HttpResponseMessage asynchronously. 在实际完成异步接收HttpResponseMessage之前,请先处置客户端。 You'll need to make your method async Task and await inside: 您需要使您的方法async Taskawait内部await

     public async Task SendDataAsync(Email email) { using (var client = new HttpClient()) { var response = await client.PostAsync(email); } } 
  2. Currently, your SendDataParallel doesn't compile. 当前,您的SendDataParallel无法编译。 Again, it needs to return a Task : 同样,它需要返回Task

     public Task SendEmailsAsync(IList<Email> emails) { var emailTasks = emails.Select(SendDataAsync); return Task.WhenAll(allTasks); } 
  3. At the top, you'll need to await on SendEmailsAsync : 在顶部,您需要await SendEmailsAsync

     public async Task LoadDataAsync() { while (Main.IsProcessRunning) { var emails = new dummyRepositories().GetAllEmails(); await SendEmailsAsync(emails); } } 

Edit: 编辑:

If you're running this inside a windows service, you can offload it to Task.Run and use the async keyword: 如果要在Windows服务中运行此程序,则可以将其卸载到Task.Run并使用async关键字:

var controller = new Controller();
_processThread = Task.Run(async () => await controller.LoadDataAsync());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM