HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Task Parallel Library and Mailkit

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
mailkitparallellibraryandtask

Problem

I have a use case where I need to process about 80,000 emails per day. The client has an existing process that takes about 1/sec per email and is running out of time before the next batch comes in. I implemented a solution using the MailKit library and I am trying to implement some parallel tasks using TPL. I tried both a Pop3 client and IMAP client and the IMAP client seems to be faster. Plus, since IMAP supports multiple clients connecting at the same time so I figured that would be better for TPL.

I tested the code with a small sample of 100 emails and trying different numbers of parallel tasks. The results are below.

I'd appreciate any advice on my code below or other improvement suggestions on how to make it faster.

```
private static int _num_of_threads = 1;
private static int _num_of_messages = 100;

public override async void DoWork()
{
try
{
IList uids = new List();
uids = GetUids();

//shrink the list for now
uids = uids.Take(_num_of_messages).ToList();

//create {_num_of_threads} lists
List> list_of_list_of_uids = new List>();
list_of_list_of_uids = SplitUids(uids);

// create the TPL tasks
Task[] tasks = new Task[_num_of_threads];
for (int index = 0; index
{
int i = (int)obj;
GetMessages(list_of_list_of_uids[i]);
}, index);
}
Task.WaitAll(tasks);
}
catch (Exception ex)
{
}
}

private List GetUids()
{
IList uids = new List();

using (var client = new ImapClient())
{
try
{
client.Connect("", 993, SecureSocketOptions.SslOnConnect);
client.Authenticate(, );
client.Inbox.Open(FolderAccess.ReadOnly);

uids = client.Inbox.Search(SearchQuery.All);
}
finally
{
if (client.IsConnected)
{
client.Disconnect(true);
}
}
}
r

Solution

My suggestions

  • Use var. For example in this piece of code List> list_of_list_of_uids = new List>(); is will be much more readable



-
I think the code under is redundant. Because using keyword (when it is compiled into IL code) already contains finally statement with Dispose inside. I am pretty sure that Dispose of ImapClient class will disconnect(if needed) itself, so you don't need to do it once again.

finally
{
    if (client.IsConnected)
    {
        client.Disconnect(true);
    }
}


-
I do not see how to significantly improve performance of your code. Only minor suggestion. The capacity of your lists in method SplitUids can be calculated in advance, so use constructor with capacity here IList uids = new List(); It will improve performance a little bit

If performance is critical in your case you should paste your for this // process aggregates a bunch of data and sends the result off to a web service to be put into a DB. I suppose these operations are quite time-consuming(because of database and web service) and might be improved.

Code Snippets

finally
{
    if (client.IsConnected)
    {
        client.Disconnect(true);
    }
}

Context

StackExchange Code Review Q#135996, answer score: 2

Revisions (0)

No revisions yet.