在同步调用方法中调用async await方法

本文关键字:调用 方法 await async 同步 | 更新日期: 2023-09-27 18:08:11

这只是关于我在窗口服务中所做的事情的想法。我从这个视频中得到了并行处理的想法。

我有两个不同的方法和一个模型类。

模型类代码:

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

方法是这样的:

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);
    }
}

我只想获得所有排队的电子邮件,然后并行发送,然后等待,直到它已经发送。我避免在我收到的每封电子邮件中使用foreach

在同步调用方法中调用async await方法

让我们从底部开始:

  1. 您在实际完成异步接收HttpResponseMessage之前处置您的客户端。你需要把你的方法async Taskawait放在里面:

    public async Task SendDataAsync(Email email)
    {
        using (var client = new HttpClient())
        {
            var response = await client.PostAsync(email);
        }
    }
    
  2. 目前,你的SendDataParallel不编译。同样,它需要返回一个Task:

    public Task SendEmailsAsync(IList<Email> emails)
    {
        var emailTasks = emails.Select(SendDataAsync);
        return Task.WhenAll(allTasks);
    }
    
  3. 在顶部,你需要在SendEmailsAsync上添加await:

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

如果你在windows服务中运行这个,你可以卸载它到Task.Run,并使用async关键字:

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

你的编译器没有突出显示你的错误代码吗?

如果你将你的方法标记为async而它不返回任何值,你应该将你的返回类型设置为Task,而不是void:

public async Task SendDataParallel(IList<Email> emails){
    var allTasks = emails.Select(SendDataAsync);
    await Task.WhenAll(allTasks);
}
你的第二个方法也应该返回一个Task,否则你想(a)在第一个方法中等待什么?
public async Task SendDataAsync(Email email){
    using (var client = new HttpClient())
    {
        return client.PostAsync(email);
    }
}

现在你可以选择所有的SendDataAsync任务在senddataparlil和。wait()它的任务在LoadData同步模式:

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

更多信息可以在MSDN上的其他SO问题和文档中找到阅读答案:

    谁能解释一下async/await?.Net 4.5中Async/Await的简要说明
  • 如何使用asyncawait以及何时使用
  • 异步编程与Async和Await

当你使用LINQ的Select(),这是基于foreach周期下一篇文章也可能是有用的:循环内嵌套任务