Asynchronous operation cannot be started at this time - c#

I am here just trying to download the emails in "INBOX" from the server using IMAP with ComponentPro .net component (Asynchronous Task-Based Approach) but it throws the error every time when I try Asynchronous method.
I already got Inbox emails downloaded using IMAP with Synchronous approach but this takes nearly 3-4 minutes to download atleast 80+ emails, So I want to try asynchronous approach any suggestions on this as I am trying asynchronous approach for the first time.
Error:
An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle.
Controller Code:
public ActionResult ImportEmailDemo()
{
var sImportedEmails = ARepository.ImportEmailForDemo();
return null;
}
Repository Code:
public async Task<string> ImportEmailForDemo()
{
//Async
// Create a new instance of the Imap class.
Imap client1 = new Imap();
// Connect to the server.
client1.Connect("Server Address");
// Or you can specify the IMAP port with
// client.Connect("myserver", 143);
// Login to the server.
client1.Authenticate("EmailID", "Password");
// Select 'INBOX' mailbox.
client1.Select("INBOX");
// Download a mail message with sequence number 1.
ComponentPro.Net.Mail.MailMessage msg = await client1.DownloadMailMessageAsync(1);
// ...
Console.WriteLine("Message downloaded successfully.");
Console.WriteLine("Message ID: {0}, Subject: {1}", msg.MessageIdentifier, msg.Subject);
// Disconnect.
client1.Disconnect();
return null;
}
I tried with different ways to resolve the error looking in internet but nothing worked for me, Can any one help me out.
Cheers!!

I already got Inbox emails downloaded using IMAP with Synchronous approach but this takes nearly 3-4 minutes to download atleast 80+ emails, So I want to try asynchronous approach
Asynchronous won't be any faster.
An asynchronous operation cannot be started at this time.
This error occurs when your code starts an asynchronous operation within a synchronous handler. You should not be using Wait or Result; instead, you need to await the returned task, which makes that method async, etc., until your handler is changed to be asynchronous.
But as noted above, using async is not going to make it faster anyway.

Related

Respond to MailGun's HTTP post and then process the message

When receiving mail through MailGun they require a response within a limited time. I have two issues with this:
1) After receiving the message I need to process and record it in my CRM which takes some time. This causes MailGun to time out before I get to send a response. Then MailGun resends the message again and again as it continues to time out.
2) MailGun's post is not async but the api calls to my CRM are async.
So I need to send MailGun a 200 response and then continue to process the message. And that process needs to be in async.
The below code shows what I want to have happen. I tried using tasks and couldn't get it working. There are times when many emails can come in a once (like when initializing someone's account) if the solution requires some sort of parallel tasks or threads it would need to handle many of them.
public class HomeController : Controller
{
[HttpPost]
[Route("mail1")]
public ActionResult Mail()
{
var emailObj = MailGun.Receive(Request);
return Content("ok");
_ = await CRM.SendToEmailApp(emailObj);
}
}
Thank you for the help!
The easiest way to do what you are describing (which is not recommended, because you may lose some results if your app crash) is to use a fire & forget task:
var emailObj = MailGun.Receive(Request);
Task.Run(async () => await CRM.SendToEmailApp(emailObj));
return Content("ok");
But, I think what you really want is sort of a Message Queue, by using a message queue you put the message in the queue (which is fast enough) and return immediately, at the same time a processor is processing the message queue and saves the result in the CRM.
This is what it'll look like when you use a message queueing broker.

I have a long running process which I call in my Service Bus Queue. I want it to continue beyond 5 minutes

I have a long running process which performs matches between millions of records I call this code using a Service Bus, However when my process passes the 5 minute limit Azure starts processing the already processed records from the start again.
How can I avoid this
Here is my code:
private static async Task ProcessMessagesAsync(Message message, CancellationToken token)
{
long receivedMessageTrasactionId = 0;
try
{
IQueueClient queueClient = new QueueClient(serviceBusConnectionString, serviceBusQueueName, ReceiveMode.PeekLock);
// Process the message
receivedMessageTrasactionId = Convert.ToInt64(Encoding.UTF8.GetString(message.Body));
// My Very Long Running Method
await DataCleanse.PerformDataCleanse(receivedMessageTrasactionId);
//Get Transaction and Metric details
await queueClient.CompleteAsync(message.SystemProperties.LockToken);
}
catch (Exception ex)
{
Log4NetErrorLogger(ex);
throw ex;
}
}
Messages are intended for notifications and not long running processing.
You've got a fewoptions:
Receive the message and rely on receiver's RenewLock() operation to extend the lock.
Use user-callback API and specify maximum processing time, if known, via MessageHandlerOptions.MaxAutoRenewDuration setting to auto-renew message's lock.
Record the processing started but do not complete the incoming message. Rather leverage message deferral feature, sending yourself a new delayed message with the reference to the deferred message SequenceNumber. This will allow you to periodically receive a "reminder" message to see if the work is finished. If it is, complete the deferred message by its SequenceNumber. Otherise, complete the "reminder" message along with sending a new one. This approach would require some level of your architecture redesign.
Similar to option 3, but offload processing to an external process that will report the status later. There are frameworks that can help you with that. MassTransit or NServiceBus. The latter has a sample you can download and play with.
Note that option 1 and 2 are not guaranteed as those are client-side initiated operations.

Twilio API ApiConnectionException "A Task Was Canceled"

I'm using the Twilio C# API to send batches of messages to the Twilio API (typically small amounts, but can grow to several thousand at a time), and in an effort to make the process faster, I started switching everything over to asynchronous calls (as well as some parallel foreaches).
The Twilio API works most of the time when it's completely synchronous, but when I change the request to be asynchronous, I start to get heaps of errors. They all essentially say:
Connection Error: POST and the internal error is A task was canceled.
After doing some digging, I've determined that the Twilio API is built on top of the HttpClient, and it uses the client to send all its requests. However, I can't figure out how to make it all work properly. On average, when sending batches with over 3,000 messages, roughly 20% of them fail.
My sending code is pretty basic
// async SendTextNotificationsAsync
try
{
var result = MessageResource.Create(
to,
from: new PhoneNumber(PhoneNumber),
body: message);
return result;
}
catch (ApiException ex) // API exception, probably an invalid number.
{
LogTwilioBadNumber(ex, phone);
return null;
}
catch (ApiConnectionException ex) // Connection error, let's reattempt
{
if (tryAttempt < 3)
{
System.Threading.Thread.Sleep(500);
// failed call again
return await SendTextNotificationsAsync(phone, message, tryAttempt + 1);
}
if (tryAttempt >= 3)
{
LogTwilioConnectionException(ex, phone, patientId, tryAttempt);
}
return null;
}
The above is called from another method that looks something like:
// async void CompleteCampaignsAsync
await Task.Run(() => Parallel.ForEach(campaign.Details, async n =>
{
await com.SendTextNotificationsAsync(to, message);
}));
And finally, the controller simply calls something like so:
// Don't wait for this to finish, internal processes handle logging
// Will get a time-out error if we wait for this.
await Task.Run(() => cl.CompleteCampaignsAsync()).ConfigureAwait(false);
There are several other steps and layers, so the above is massively simplified. Everything is asynchronous and everything is awaited. The only real exception is the main controller due to it being a long running process that needs to just get kicked off.
In the first method, I've tried both MessageResource.Create and MessageResource.CreateAsync. In the latter, I get through about 80 messages before its an unending stream of task cancelled errors. In the former, the process runs to completion, but roughly 20%-50% of the tasks fail.
Is there anything immediately obviously wrong that would allow me to correct this?

async method in ASP.NET MVC

I want to create a async method which will open a thread and complete several tasks that is relatively independent to the current http request (for example, sending emails and generating files both of which takes time)
I created the following method
private static async Task<T> DoSeparateTask<T>(Func<T> func)
{
return func();
}
and want to use it in such a way:
private static void DoSomething()
{
#step 1 - some code for immediate processing
#step 2 - some code for generating documents which takes time
var additionalDocumentGenerationWork = DoSeparateTask<Document>(() =>{
#additional code for generating Document
#even though it returns Document, but 99% time it wont be used in this method
});
#step 3 - some code for sending SMTP email which takes time
var additionalDocumentGenerationWork = DoSeparateTask<bool>(() =>{
#additional code for sending email
return true;
});
}
Everything compiles, however when I run the web application, it still keeps loading and waiting everything to complete before rendering the web page. As the 2 additional tasks (email and documents) are not relevant for displaying the webpage, how can I achieve such by using the async modifiers?
Or if my understanding of async is wrong... please help me to correct...
Many thanks.
Or if my understanding of async is wrong... please help me to correct...
As I explain on my blog, async does not change the HTTP protocol. At the end of the day, you only have one response for each request. To put another way, async yields to the thread pool, not to the client.
What you're looking for is a way to do operations outside the request/response lifecycle, which is not directly supported by ASP.NET. I describe a few approaches on my blog. The best (most reliable) approach is to place the work into a queue, and have an independent backend that processes the queue (such as an Azure worker role).
You don't need the DoSeparateTask<T>() method. Instead, just use Task.Run<T>():
private static async Task DoSomething()
{
// #step 1 - some code for immediate processing
// #step 2 - some code for generating documents which takes time
var additionalDocumentGenerationWork1 = await Task.Run(() =>
{
// #additional code for generating Document
// #even though it returns Document, but 99% time it wont be used in this method
});
// #step 3 - some code for sending SMTP email which takes time
var additionalDocumentGenerationWork2 = await Task.Run(() =>
{
// #additional code for sending email
return true;
});
}
Note that the type of additionalDocumentGenerationWork1 and additionalDocumentGenerationWork2 (you used the same name twice in your example, so I changed it above to make the code legal) are Document and bool respectively. You can use additionalDocumentGenerationWork1 in your second task invocation if you like (e.g. to pass the result of the first operation).

Issue using Task.Factory.FromAsync

I enjoyed the new C# 5's async and await and I want to set it up to one of my previous Tcp application which I used the async whay (not async & await, in fact Begin*, End*)
in my application every message have a response, so every time you use BeginSend, you will receive a message related the message you first sent. (lets suppose command and it's report)
I want to add a new function called RequestAsync that you send your message and wait till the response comes. let me show the usage
string response = await RequestAsync("hi");
on this occasion, you will send a "hi" message and then code waits till the response related to this comes.
I had problems using Task.Factory.FromAsync, so I tried the following code, i want to make sure the performance is roughly the same as TaskFactory way.
public async Task<IRequestResult> SendRequestAsync(IRequest request, string message)
{
IRequestResult result = BeginSendRequest(request, message);
while (!result.IsCompleted)
{
await Task.Delay(1);
}
return result;
}
and BeginRequest is my own method.
Sincerely yours,
Peyman Mortazavi
No, that's going to be pretty awful in terms of efficiency - you'll be waking up and requiring rescheduling every 5 milliseconds. You've added latency while you effectively sleep between cycles as well.
You should go back to trying to use Task.Factory.FromAsync - you haven't told us what went wrong when you tried that, so it's hard to help you fix it... It's possible that you haven't implemented the asynchronous programming model pattern correctly to start with. (The fact that you're not providing a callback to your BeginSendRequest method is suggestive of that.)
I hope your real code doesn't have catch {} either...
Poling can never be efficient as IO completion ports, and why even use an async method if you are only waiting for it and not doing anything in the mean time, it just ads needles overhead.

Categories

Resources