0

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.

4
  • 7
    What is the question or problem? Commented Aug 17, 2015 at 9:20
  • @SriramSakthivel already edited.,. Commented Aug 17, 2015 at 9:33
  • 2
    @janmvtrinidad There is still no question here. Commented Aug 17, 2015 at 9:35
  • @AntP i put question as a comment in code.,. Commented Aug 17, 2015 at 9:41

2 Answers 2

1

Lets start at the bottom:

  1. You dispose your client before you actually finish receiving the HttpResponseMessage asynchronously. You'll need to make your method async Task and await inside:

    public async Task SendDataAsync(Email email)
    {
        using (var client = new HttpClient())
        {
            var response = await client.PostAsync(email);
        }
    }
    
  2. Currently, your SendDataParallel doesn't compile. Again, it needs to return a 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:

    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:

var controller = new Controller();
_processThread = Task.Run(async () => await controller.LoadDataAsync());
Sign up to request clarification or add additional context in comments.

6 Comments

It's okay to add static type for LoadDataAsync.,?
You want the method to be static?
I will be using LoadData to call as a background service in windows service.,.
@janmvtrinidad Ok, but what does that have to do with a static method?
I will create a Thread like this one _processThread = new Thread(Controllers.LoadData) { IsBackground = true };, it needs to be a static to place LoadData as parameters for Thread.
|
1

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:

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?

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:

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:

And as you used LINQ's Select() which is based on foreach cycle next article also could be useful: Nested task inside loop

1 Comment

I will use an wait() on my LoadData().., I think it will have an error on SendDataAsync, there is no await keyword on return.., Anyway thanks for your solution.,.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.