MSMQ - ReceiveCompleted - Process Messages async - c#

I am using the BeginnReceive method and ReceiveCompleted eventhandler to listen and process messages from a MSMQ.
I have put the BeginReceive method at the beginning of the ReceiveCompleted eventhandler.
It looks like it's working fine in my console application.
Right now, the messages are processed asynchronously.
Question:
Is this safe regarding thread-safety?
All examples I saw put the BeginReceive call to the end of the completed eventhandler. So I ask myself are there any issues when putting it at the very beginning of the completed handler?
private void InitializeQueue()
{
try
{
_mq = MessageQueue.GetPrivateQueuesByMachine(_queueServerName).Where(qu => qu.Path == _queueAddress).FirstOrDefault();
_mq.Formatter = new BinaryMessageFormatter();
_mq.ReceiveCompleted += MessageReceiveCompleted;
}
catch (Exception ex)
{
Trace.WriteLine("Failed to initialize Queue!" + Environment.NewLine + " Error:" + Environment.NewLine + ex.Message);
throw;
}
}
async void MessageReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
_mq.BeginReceive();
try
{
await ProcessMessageAsync(e.Message);
}
catch (Exception ex)
{
Trace.WriteLine("Error occured during report fetching:" + Environment.NewLine + ex.Message);
throw;
}
}

Yes your approach with async/await will handle the threads safely.c# asynchronous approach with these keywords will take care.
Being more specific about my answer the event handler method messagereceived (the method name should end with async)calls and awaits on the async method, if there is any blocking work inside this method the thread it's suspends there and executes further until other work finishes and returns, like in this case the processmessage async might be blocking and there can be further execution of call but I don't see you leverage it since there is nothing you are doing after calling processmessageasync,so the thread will be executing this if you ask if it's thread safe yes but asynchronous approach is not fully leveraged

Related

C# - return boolean from Async method

I have Async method which is called inside button_click. Async method runs 3 different void's and each void has It's own error handling. If any error inside those 3 methods occure I want to show that particular error message and stop code inside button_click - which also runs more non-async method and has It's error handling. What I did was this (example):
private void button1_Click(object sender, EventArgs e)
{
try
{
//calling non-async method, if It fails It should show error
//inside this event
Method1();
if (TestAsync().IsCanceled)
{
return;
}
MessageBox.Show("Test");
}
catch (Exception)
{
MessageBox.Show("Async method failed and this message should not be diplayed!");
throw;
}
}
public async Task<bool> TestAsync()
{
bool completed = await Task.Run(() => MethodToComplete());
return completed;
}
private bool MethodToComplete()
{
try
{
//renaming file, but intentionally fail for test purpose
Directory.Move("fail_this_method", "fail");
return true;
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
return true;
throw;
}
}
The result of this example is - It does display error message from void which is called asynchronously and doesn't show error message from button_click. But It also displays MessageBox.Show("Test"); which shouldn't, code in button_click should stop immidiately if Async fails.
I hope I was clear enough, any help kindly appreaciated !
Before async-await there were other task handling methods, like Task.ContinueWith, Task.IsCanceled etc.
If you plan to use async-await, don't mix them with these older functions.
When you decide to use async-await, stick to the following rules:
only declare a function async if it awaits a call to another async function
every async function should return Task<TResult> instead of TResult and Task instead of void
There is one exception: an async event handler returns void
Furthermore:
If you call an async function, but you do not need the result immediately, consider not to await yet, but do the other things. Start awaiting when you need the results of the async function
After the await the thread that continues may be a different thread. But it has the same context. This has the effect that you can regard this as if it is the original thread. No need for InvokeRequired, locks and mutexes
If you don't need the same context, consider ConfigureAwait(false) after the await. This will speed up the process, with the disadvantage that the continuing thread does not have the user interface context. Therefore you can't access windows Form controls.
Keeping this in mind, you code could be as follows:
private async void button1_Click(object sender, EventArgs e)
{
// this function must be async because if awaits
// it is an event hander, hence it returns void instead of Task
try
{
Method1();
// call TestAsync, if you do not need the result right now,
// do not await yet
var myTask = TestAsync();
// as soon as TestAsync has to await, it continues here:
// results from TestAsync are not available yet
DoSomeOtherProcessing();
// now you need the result from testAsync; await the Task
bool result = await myTask;
ProcessResult(result);
}
catch (Exception)
{
...
}
}
A Task that is cancelled, should throw TaskCanceledException. You should not check MyTask.IsCanceled, but catch this exception.
Articles that helped me understanding async-await
This interview with Eric Lippert Search somewhere in the middle for async-await. Eric compares async-await with a cook making dinner. Once he put on the kettle, he does not idly wait for the water to boil, but looks around to see if he can do other things instead, like chopping onions
async-await by the ever so helpful Stephen Cleary

Wait for async task on application exit from UI thread

I'm writing an UI app. If some exception happens I need to do some work before application exit.
So I subscribed to AppDomain.CurrentDomain.UnhandledException event.
AppDomain.CurrentDomain.UnhandledException += HandleException;
HandleException method performs async saving to remote(because there are no sync api).
private void HandleException(object sender, UnhandledExceptionEventArgs args)
{
foreach (var user in UsersCollection.ToArray())
{
try
{
foreach (var session in user.Sessions.ToArray())
{
try
{
SaveSessionAsync(session).Wait();
}
catch (Exception e)
{
Logger.Error("Can't save session: " + session, e);
}
}
}
catch (Exception e)
{
Logger.Error("Can't save sessions of user " + user, e);
}
}
}
Before application exit I need to be sure that I saved all sessions(tried, at least). But if I put Wait() there I get a deadlock and application never stops.
As far as I know, await may help me in normal situation(when I'm in UI thread but not in app termination state), but await does not awaits on application exit. So my saving tasks may be aborted. But I need them to finish.
Is there a way of waiting for guaranteed finish of SaveSessionAsync task without creating a deadlock?
BTW: SaveSessionAsync has Parse.com API inside
You only used part of the syntax you need to run it in a non-async method. Utilizing Task.Run() will run it in an asynchronous fashion without having to use await.
Try this:
Task.Run(() => SaveSessionAsync(session)).Wait();

How to propagate thread exceptions back to application exception handler

http://msdn.microsoft.com/en-us/magazine/gg598924.aspx
Why exceptions are not propagated by WPF Dispatcher.Invoke?
How can I allow Task exceptions to propagate back to the UI thread?
In the code below I need to propagate execeptions that are thrown in the tasks and their continuations back up to the ui thread where they will be handled by LogException. If I need to re-throw an exception somewhere along the line thats fine with me. Whatever works. How do I do that?
I referenced some questions that are similar to mine but I do not see an answer that is relevant to my app.
Edit 3: posted a simplified example
Edit 2:
See this:
http://msdn.microsoft.com/en-us/library/dd997415(v=vs.100).aspx
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
FireAndForget();
WaitOnTask();
}
private void FireAndForget()
{
Task t1 = Task.Factory.StartNew(() =>
{
Thread.Sleep(3000);
throw new Exception("boo");
});
Task c1 = t1.ContinueWith((t) =>
{
// The app global exception handler will not catch this.
}, TaskContinuationOptions.OnlyOnFaulted);
//MessageBox.Show("Task is running");
}
private void WaitOnTask()
{
Task t1 = Task.Factory.StartNew(() =>
{
throw new Exception("boo");
});
try
{
t1.Wait();
}
catch (Exception ex)
{
// The app global exception handler will catch this:
throw new Exception("Task", ex);
}
}
}
public partial class App : Application
{
public App()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.Current.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(Current_DispatcherUnhandledException);
//System.Threading.Tasks.TaskScheduler.UnobservedTaskException += new EventHandler<System.Threading.Tasks.UnobservedTaskExceptionEventArgs>(TaskScheduler_UnobservedTaskException);
}
void TaskScheduler_UnobservedTaskException(object sender, System.Threading.Tasks.UnobservedTaskExceptionEventArgs e)
{
LogException(e.Exception);
}
void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
LogException(e.Exception);
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
LogException(e.ExceptionObject as Exception);
}
private void LogException(Exception ex)
{
// log it
string error = "This app has encountered an unexpected error . The error message is:" + Environment.NewLine + ex.Message + Environment.NewLine;
Exception tmp = ex.InnerException;
while (tmp != null)
{
error += "Inner exception is: " + Environment.NewLine + tmp.Message + Environment.NewLine;
tmp = tmp.InnerException;
}
error += "Please press OK to exit.";
MessageBox.Show(error, "Error");
Environment.Exit(-1);
}
}
When you use StartNew or ContinueWith, any exceptions are placed on the returned Task.
There are two problems with marshaling exceptions:
Task.Exception wraps your exception in an AggregateException.
When you throw an exception later (e.g., on another thread), the original call stack is lost.
For the first problem, some people use the Flatten or Handle members to work directly with AggregateException. I prefer unwrapping the exceptions by dealing with Task.Exception.InnerException instead of Task.Exception.
For the second problem, some people work around it by wrapping it in another exception, but I have taken an alternative approach. .NET 4.5 introduced ExceptionDispatchInfo, which is the correct way to do this. In .NET 4.0 you can hack something like this:
public static Exception Rethrow(this Exception ex)
{
typeof(Exception).GetMethod("PrepForRemoting",
BindingFlags.NonPublic | BindingFlags.Instance)
.Invoke(ex, new object[0]);
throw ex;
}
I'm not sure if i'm missing something here, but if you use
TaskScheduler.FromCurrentSynchronizationContext() as the second parameter to ContinueWith
then it will be marshaled back onto your UX thread.
I actually wrote a blog post about it if you want a little more of a sample.
http://www.briankeating.net/post/Why-I-love-the-Task-library
Kr,
Brian.
The answer to the question is found here:
http://blogs.msdn.com/b/pfxteam/archive/2009/05/31/9674669.aspx
Basically there are two scenarios: Situations where you can wait on the task and situations where you cannot i.e. fire and forget.
In situations where you can wait on the task, wrap it in a try block as shown in the question and rethrow the error. The global app handler will catch it.
In situtions where you cannot wait on the task you have to call your logger manually. There is no application level handler that will catch the error. There is a possibility that TaskScheduler.UnobservedTaskException will fire, however that event is IMHO highly circumstantial and fragile and not a good option.
To propagate the exceptions in your code you need to Wait on all the tasks. If you make the following changes to your FireAndForget method the Exception in the nested Task will be propagated back to the calling thread.
private void FireAndForget()
{
var tasks = new Task[2];
tasks[0] = Task.Factory.StartNew(() =>
{
Thread.Sleep(3000);
throw new Exception("boo");
});
tasks[1] = tasks[0].ContinueWith((t) =>
{
throw new Exception("nested boo", tasks[0].Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
try
{
Task.WaitAll(tasks);
}
catch (AggregateException ex)
{
throw new Exception("Task", ex);
}
}
Of course this is no longer a "fire and forget" method. If waiting on the tasks is undesirable you will need to write to your log file from within the continuation.
You can await the completion of the task to receive exception from the task code.
try{
await Task.Factory.StartNew(() => throw Exception("hello"));
}catch{
// will get exception here
}

Azure ServiceBus & async - To be, or not to be?

I'm running Service Bus on Azure, pumping about 10-100 messages per second.
Recently I've switched to .net 4.5 and all excited refactored all the code to have 'async' and 'await' at least twice in each line to make sure it's done 'properly' :)
Now I'm wondering whether it's actually for better or for worse. If you could have a look at the code snippets and let me know what your thoughts are. I especially worried if the thread context switching is not giving me more grief than benefit, from all the asynchrony... (looking at !dumpheap it's definitely a factor)
Just a bit of description - I will be posting 2 methods - one that does a while loop on a ConcurrentQueue, waiting for new messages and the other method that sends one message at a time. I'm also using the Transient Fault Handling block exactly as Dr. Azure prescribed.
Sending loop (started at the beginning, waiting for new messages):
private async void SendingLoop()
{
try
{
await this.RecreateMessageFactory();
this.loopSemaphore.Reset();
Buffer<SendMessage> message = null;
while (true)
{
if (this.cancel.Token.IsCancellationRequested)
{
break;
}
this.semaphore.WaitOne();
if (this.cancel.Token.IsCancellationRequested)
{
break;
}
while (this.queue.TryDequeue(out message))
{
try
{
using (message)
{
//only take send the latest message
if (!this.queue.IsEmpty)
{
this.Log.Debug("Skipping qeued message, Topic: " + message.Value.Topic);
continue;
}
else
{
if (this.Topic == null || this.Topic.Path != message.Value.Topic)
await this.EnsureTopicExists(message.Value.Topic, this.cancel.Token);
if (this.cancel.Token.IsCancellationRequested)
break;
await this.SendMessage(message, this.cancel.Token);
}
}
}
catch (OperationCanceledException)
{
break;
}
catch (Exception ex)
{
ex.LogError();
}
}
}
}
catch (OperationCanceledException)
{ }
catch (Exception ex)
{
ex.LogError();
}
finally
{
if (this.loopSemaphore != null)
this.loopSemaphore.Set();
}
}
Sending a message:
private async Task SendMessage(Buffer<SendMessage> message, CancellationToken cancellationToken)
{
//this.Log.Debug("MessageBroadcaster.SendMessage to " + this.GetTopic());
bool entityNotFound = false;
if (this.MessageSender.IsClosed)
{
//this.Log.Debug("MessageBroadcaster.SendMessage MessageSender closed, recreating " + this.GetTopic());
await this.EnsureMessageSender(cancellationToken);
}
try
{
await this.sendMessageRetryPolicy.ExecuteAsync(async () =>
{
message.Value.Body.Seek(0, SeekOrigin.Begin);
using (var msg = new BrokeredMessage(message.Value.Body, false))
{
await Task.Factory.FromAsync(this.MessageSender.BeginSend, this.MessageSender.EndSend, msg, null);
}
}, cancellationToken);
}
catch (MessagingEntityNotFoundException)
{
entityNotFound = true;
}
catch (OperationCanceledException)
{ }
catch (ObjectDisposedException)
{ }
catch (Exception ex)
{
ex.LogError();
}
if (entityNotFound)
{
if (!cancellationToken.IsCancellationRequested)
{
await this.EnsureTopicExists(message.Value.Topic, cancellationToken);
}
}
}
The code above is from a 'Sender' class that sends 1 message/second. I have about 50-100 instances running at any given time, so it could be quite a number of threads.
Btw do not worry about EnsureMessageSender, RecreateMessageFactory, EnsureTopicExists too much, they are not called that often.
Would I not be better of just having one background thread working through the message queue and sending messages synchronously, provided all I need is send one message at a time, not worry about the async stuff and avoid the overheads coming with it.
Note that usually it's a matter of milliseconds to send one Message to Azure Service Bus, it's not really expensive. (Except at times when it's slow, times out or there is a problem with Service Bus backend, it could be hanging for a while trying to send stuff).
Thanks and sorry for the long post,
Stevo
Proposed Solution
Would this example be a solution to my situation?
static void Main(string[] args)
{
var broadcaster = new BufferBlock<int>(); //queue
var cancel = new CancellationTokenSource();
var run = Task.Run(async () =>
{
try
{
while (true)
{
//check if we are not finished
if (cancel.IsCancellationRequested)
break;
//async wait until a value is available
var val = await broadcaster.ReceiveAsync(cancel.Token).ConfigureAwait(false);
int next = 0;
//greedy - eat up and ignore all the values but last
while (broadcaster.TryReceive(out next))
{
Console.WriteLine("Skipping " + val);
val = next;
}
//check if we are not finished
if (cancel.IsCancellationRequested)
break;
Console.WriteLine("Sending " + val);
//simulate sending delay
await Task.Delay(1000).ConfigureAwait(false);
Console.WriteLine("Value sent " + val);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}, cancel.Token);
//simulate sending messages. One every 200mls
for (int i = 0; i < 20; i++)
{
Console.WriteLine("Broadcasting " + i);
broadcaster.Post(i);
Thread.Sleep(200);
}
cancel.Cancel();
run.Wait();
}
You say:
The code above is from a 'Sender' class that sends 1 message/second. I
have about 50-100 instances running at any given time, so it could be
quite a number of threads.
This is a good case for async. You save lots of threads here. Async reduces context switching because it is not thread-based. It does not context-switch in case of something requiring a wait. Instead, the next work item is being processed on the same thread (if there is one).
For that reason you async solution will definitely scale better than a synchronous one. Whether it actually uses less CPU at 50-100 instances of your workflow needs to be measured. The more instances there are the higher the probability of async being faster becomes.
Now, there is one problem with the implementation: You're using a ConcurrentQueue which is not async-ready. So you actually do use 50-100 threads even in your async version. They will either block (which you wanted to avoid) or busy-wait burning 100% CPU (which seems to be the case in your implementation!). You need to get rid of this problem and make the queuing async, too. Maybe a SemaphoreSlim is of help here as it can be waited on asynchronously.
First, keep in mind that Task != Thread. Tasks (and async method continuations) are scheduled to the thread pool, where Microsoft has put in tons of optimizations that work wonders as long as your tasks are fairly short.
Reviewing your code, one line raises a flag: semaphore.WaitOne. I assume you're using this as a kind of signal that there is data available in the queue. This is bad because it's a blocking wait inside an async method. By using a blocking wait, the code changes from a lightweight continuation into a much heavier thread pool thread.
So, I would follow #usr's recommendation and replace the queue (and the semaphore) with an async-ready queue. TPL Dataflow's BufferBlock<T> is an async-ready producer/consumer queue available via NuGet. I recommend this one first because it sounds like your project could benefit from using dataflow more extensively than just as a queue (but the queue is a fine place to start).
Other async-ready data structures exist; my AsyncEx library has a couple of them. It's also not hard to build a simple one yourself; I have a blog post on the subject. But I recommend TPL Dataflow in your situation.

Proper exception handling when invoking WCF callback method

I have a series of WCF services that invoke methods on the client again (using WcfDuplexChannels) based on events at the server side. However, it seems there are quite some exceptions that can occur, so right now I have a huge try/catch block around every line calling back to the client, ending with disabling of the event in case any exception occurs. Besides being cumbersome to write every time, I'm not sure if I could simplify the try catch block by catching just a few base exceptions? Right now I don't really care what's causing the exceptions (I don't care whether it's faulted, aborted, disposed or timed out) but I do log the different exceptions.
I also read about IErrorHandler, but will that actually be suitable when invoking a method on the client?
Here's a sample of my current strategy:
private void OnProductChanged(List<DTO> products)
{
try
{
client.OnProductChanged(products);
return;
}
catch (TimeoutException)
{
log.Info("Communication to client timed out.");
}
catch (CommunicationObjectAbortedException)
{
log.Info("Connection to client is in aborted state.");
}
catch (CommunicationObjectFaultedException)
{
log.Info("Connection to client is in faulted state.");
}
catch (CommunicationException ce)
{
log.InfoFormat("CommunicationException occured on product change notification: {0}.", ce.Message);
}
catch (ObjectDisposedException)
{
log.Info("Communication channel is disposed.");
}
catch (Exception e)
{
log.WarnFormat("Unhandled {0} on client callback: {1}", e.GetType(), e.Message);
}
SendProductChanged = false;
}
The SendProductChanged = false; line will take care of unbinding the event handler.
You can write a wrapper method which takes Actions of Funcs as parameters and you can use try catch blocks inside this function. You can call your functions using this function; something like:
public void CallMethod(Action methodToBeCalled)
{
try
{
methodToBeCalled();
}
catch
.....
....
}
Then call your functions like:
CallMethod(() => client.OnProductChanged(products));

Categories