Calling Method so that program doesn't get blocked - c#

I need to call SendEmail() in my C# code below so that my program doesn't get blocked due to SendEmail() method taking a lot of time and or failing.
Here's my C# code:(I'm using .Net 4.5)
private void MyMethod()
{
DoSomething();
SendEmail();
}
Can I achieve the same using following please?Or is there any other better approach ?Is using async/await a better approach for achieving this?
public void MyMethod()
{
DoSomething();
try
{
string emailBody = "TestBody";
string emailSubject = "TestSubject";
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(SendEmailAlert), arrEmailInfo);
}
catch (Exception ex)
{
//Log error message
}
}
private void SendEmailAlert(object state)
{
string[] arrEmailnfo = state as string[];
MyClassX.SendAlert(arrEmailnfo[0], arrEmailnfo[1]);
}
And In case I need to make SendEmailAlert() method as fire and forget, I can use code like this Would that be correct? ---->
Task.Run(()=> SendEmailAlert(arrEmailInfo));
Thanks.

Async await can definitely help you. When you have CPU-bound work to do asynchronously, you can use Task.Run(). This method can be "awaited" so that the code will resume after the task is done.
Here's what I would do in your case:
public async Task MyMethod()
{
DoSomething();
try
{
string emailBody = "TestBody";
string emailSubject = "TestSubject";
await Task.Run(()=> SendEmailAlert(arrEmailInfo));
//Insert code to execute when SendEmailAlert is completed.
//Be aware that the SynchronizationContext is not the same once you have resumed. You might not be on the main thread here
}
catch (Exception ex)
{
//Log error message
}
}
private void SendEmailAlert(string[] arrEmailInfo)
{
MyClassX.SendAlert(arrEmailnfo[0], arrEmailnfo[1]);
}

Related

C#: calling [async] method without [await] will not catch its thrown exception?

I'm having this code snippet:
class Program
{
public static async Task ProcessAsync(string s)
{
Console.WriteLine("call function");
if (s == null)
{
Console.WriteLine("throw");
throw new ArgumentNullException("s");
}
Console.WriteLine("print");
await Task.Run(() => Console.WriteLine(s));
Console.WriteLine("end");
}
public static void Main(string[] args)
{
try
{
ProcessAsync(null);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
It runs and prints:
call function
throw
Ok, and exception is thrown, but the main function's try/catch is not able to catch the exception, if I remove the try/catch, main doesn't report unhandled exception either. This is very weird, I googled and it says there's trap in [await] but doesn't explain how and why.
So my question, why here the exception is not caught, what's the pitfalls of using await?
Thanks a lot.
Within an async method, any exceptions are caught by the runtime and placed on the returned Task. If your code ignores the Task returned by an async method, then it will not observe those exceptions. Most tasks should be awaited at some point to observe their results (including exceptions).
The easiest solution is to make your Main asynchronous:
public static async Task Main(string[] args)
{
try
{
await ProcessAsync(null);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}

C# await udpClient.ReceiveAsync() fails and terminates program

I'm running a C# console application with .NET 4.5.1. When I run the following function the udpClient.ReceiveAsync() call below silently terminates the program with no exception. How do I debug this?
public async void Run()
{
try
{
var armIpAddress = IPAddress.Parse("239.1.11.1");
using (var udpClient = new UdpClient())
{
udpClient.ExclusiveAddressUse = false;
var ipEndPoint = new IPEndPoint(IPAddress.Any, 12020);
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.ExclusiveAddressUse = false;
udpClient.Client.Bind(ipEndPoint);
udpClient.JoinMulticastGroup(armIpAddress);
while (true)
{
var result = await udpClient.ReceiveAsync();
//...
}
}
catch (Exception x)
{
Console.WriteLine(x.Message);
}
}
The call to await udpClient.ReceiveAsync() is not terminating the program nor it is silently failing.
Given that this is happening, I assume you have something like this:
public static void Main(string[] args)
{
...
Run();
}
In an async void method, control is returned to the parent as soon as an await call is reached, so the flow of the program would be something like:
public static void Main(string[] args)
{
...
var armIpAddress = IPAddress.Parse("239.1.11.1");
using (var udpClient = new UdpClient())
{
udpClient.ExclusiveAddressUse = false;
.......
while (true)
{
return;
}
}
}
So the program ends due to no further blocking code.
For this to work as you would expect, change the code to this:
public static void Main(string[] args)
{
...
Run().Wait();
}
public async Task Run() { ... }
Not sure about the calling method, but with the given infomation, I would suggest the following article that has best practices around async await by #Stephen Cleary
It says to avoid async void and I am pasting an excerpt here from the article for quick reference
Async void methods can wreak havoc if the caller isn’t expecting them to be async. When the return type is Task, the caller knows it’s
dealing with a future operation; when the return type is void, the
caller might assume the method is complete by the time it returns.
This problem can crop up in many unexpected ways.
Exceptions from an Async Void Method Can’t Be Caught with Catch

Handle exception in consumer queue

public class ProducerConsumerQueue
{
public void EnqueueTask(MyTask task)
{
}
void Work()
{
while (true)
{
try
{
// my task goes here
Thread.Sleep(2000);
}
catch(Exception ex)
{
Log(ex);
}
}
}
}
Producer:
public void Add()
{
MyTask task = new MyTask();
new ProducerConsumerQueue().EnqueueTask(task);
}
I'm in .NET 3.5.
Add() method will be called by my API users. In the example above, inside the method, void work(), I'm catching the exception and logging there.
But instead of that, I would like to catch and rethrow the exception to the user. Sametime, the permanent thread that run inside the while loop, should recover from the exception by continue to the next task in the queue. My short question is - How will I throw exception that happen inside void work(), but still the consumer stay alive for next task in the queue.
Continuing our discussion from the comments, you could possibly do something like collecting all the exceptions occurring when executing a queue of tasks (however you need to execute the queue on cycles) and then throwing it back to the caller.
So something like:
public void ExecuteAllTasks()
{
var exceptions = new List<Exception>();
IEnumerable<MyTask> tasks = GetQueuedTasks(); // get all tasks (or possibly pass them to the method) ...
foreach (MyTask task in tasks)
{
try
{
// execute your tasks here ...
}
catch (Exception ex)
{
// collect all the exceptions
exceptions.Add(ex);
}
}
// throw all the errors at once
if (exceptions.Any())
throw new AggregateException(_exceptions);
}
I hope this helps.
You need to establish some sort of communications between your consumer threads and the main thread. When a consumer encounters an exception, it should notify the main thread and move on to the next task.
Since you're using Winforms, the easiest way to inform the main thread is to use Invoke. See the following question for an example.
Introduce a callback which is invoked when the task has completed:
public interface ICompletionState
{
public ITask Task { get; set; }
public Exception Exception { get; set; }
}
public class CompletionState : ICompletionState
{
public ITask Task { get; set; }
public Exception Exception { get; set; }
public Action<ICompletionState> Callback { get; set; }
}
public class ProducerConsumerQueue
{
ConcurrentQueue<CompletionState> _tasks = new ConcurrentQueue<CompletionState>();
public void EnqueueTask(ITask task, Action<ICompletionState> callback)
{
_tasks.Enqueue(new CompletionState{ Task = task, Callback = callback });
}
void Work()
{
while (true)
{
CompletionState cs;
try
{
if (!_tasks.TryDequeue(out cs))
continue;
cs.Task.Execute();
cs.Callback(cs);
}
catch(Exception ex)
{
cs.Exception = ex;
cs.Callback(cs);
}
}
}
}

Async exception handling with void

I'm using Async CTP to write an IO heavy console app. But I'm having problems with exceptions.
public static void Main()
{
while (true) {
try{
myobj.DoSomething(null);
}
catch(Exception){}
Console.Write("done");
//...
}
}
//...
public async void DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
And the following happens: "done" gets written to the console, then I get the exception in the debugger, then I press continue my program exists.
What gives?
If you give your Console application an async-compatible context (e.g., AsyncContext (docs, source) from my AsyncEx library), then you can catch exceptions that propogate out of that context, even from async void methods:
public static void Main()
{
try
{
AsyncContext.Run(() => myobj.DoSomething(null));
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
Console.Write("done");
}
public async void DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
When you call DoSomething() it basically creates a Task under the hood and starts that Task. Since you had a void signature, there is no Task object to signal back or that you could have blocked on, so execution fell straight through to done. Meanwhile the task throws an exception, which nobody is catching, which, I suspect, is why your program terminates.
I think the behavior you wanted is more like this:
public static void Main()
{
while (true) {
var t = myobj.DoSomething(null);
t.Wait();
if(t.HasException) {
break;
}
}
Console.Write("done");
//...
}
}
//...
public async Task DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
This will block on each DoSomething until it's done and exit the loop if DoSomething threw. Of course, then you are not really doing anything async. But from the pseudo code, i can't quite tell what you wanted to happen asynchronously.
Main take-away: Using void for an async method means that you loose the ability to get the exception unless you are awaiting that async method. As a sync call it basically just schedules work and the outcome disappears into the ether.

Implementing Asynchronous method

I'm looking to implement a synchronous and asynchronous version of a method within a class library. Currently I've done this so that the Async method fires off a new Thread and does it's processing. To determine if the action has completed the user should poll a property to see if it has finished.
I'd like to improve it, I think it would be better to use some form of Async callback or result, but I'm not really sure how to go about implementing it, or, if indeed it is necessary. Can anyone offer any advice?
public static void Queue(Action action, Action done) {
ThreadPool.QueueUserWorkItem(_ =>
{
try {
action();
}
catch (ThreadAbortException) { /* dont report on this */ }
catch (Exception ex) {
Debug.Assert(false, "Async thread crashed! This must be fixed. " + ex.ToString());
}
// note: this will not be called if the thread is aborted
if (done != null) done();
});
}
Usage:
Queue( () => { Console.WriteLine("doing work"); },
() => { Console.WriteLine("work was done!"); } );
You can use a callback method instead of polling.
Check out my answer on AsyncCallback
Edited:
Example of FileCopy using own async delegates with callback:
public class AsyncFileCopier
{
public delegate void FileCopyDelegate(string sourceFile, string destFile);
public static void AsynFileCopy(string sourceFile, string destFile)
{
FileCopyDelegate del = new FileCopyDelegate(FileCopy);
IAsyncResult result = del.BeginInvoke(sourceFile, destFile, CallBackAfterFileCopied, null);
}
public static void FileCopy(string sourceFile, string destFile)
{
// Code to copy the file
}
public static void CallBackAfterFileCopied(IAsyncResult result)
{
// Code to be run after file copy is done
}
}
You can call it as:
AsyncFileCopier.AsynFileCopy("abc.txt", "xyz.txt");
Asynchronous Delegates could be another option.
Read about Asynchronous Programming Using Delegates on MSDN

Categories

Resources