Thread saftey and XMLSerializer - thread-safety

Should a call to XmlSerializer.Serialize and XmlSerializer.Create be wrapped in a locked object for thread safety?
e.g.
var fileLock = new object();
lock (fileLock)
{
// Serialize here
}

The documentation for XmlSerializer says:
Thread Safety
This type is thread safe.
So you should not need this lock.

Related

Weird Behavior while missing an await keyword generates error: Cannot access a disposed context instance

I recently ran into this error. I have never came across this before so wondering!
Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'OrderDbContext'.
The only thing i missed which produced this error is the await keyword in the controller action method before _mediator.Send(checkoutCommand); Once I added the await keyword this error vanished.
What (the heck) is wrong with missing this await keyword? The error does not explicitly state that. Can someone explain why missing an await keyword cause an error that database context is disposed?
Controller Action:
public async Task<IActionResult> Checkout(CheckoutOrderCommand checkoutCommand)
{
**var id = _mediator.Send(checkoutCommand);**
return CreatedAtRoute("Get Order by Id", id);
}
CQRS Mediatr Instructions
public class CheckoutOrderCommandHandler : IRequestHandler<CheckoutOrderCommand, int>
{
private readonly IOrderUow _orderUow;
private readonly IMapper _mapper;
public CheckoutOrderCommandHandler(IOrderUow orderUow,
IMapper mapper)
{
_orderUow = orderUow;
_mapper = mapper;
}
public async Task<int> Handle(CheckoutOrderCommand request, CancellationToken cancellationToken)
{
var order = _mapper.Map<Order>(request);
// Populate base entity fields
order.CreatedBy = Constants.CurrentUser;
// create new order
var newOrder = await _orderUow.AddOrderAsync(order);
return newOrder.Id;
}
}
Unit of work implementation
public class OrderUow : IOrderUow
{
private readonly OrderDbContext _orderContext;
public OrderUow(OrderDbContext orderContext)
{
_orderContext = orderContext;
}
public async Task<Order> AddOrderAsync(Order order)
{
try
{
await _orderContext.Orders.AddAsync(order);
await _orderContext.SaveChangesAsync();
}
catch (Exception ex)
{
}
return order;
}
}
Missing an await without explicitly handling the task that is returned will mean that the code calling the asynchronous method will not create a resumption point and instead will continue executing to completion, in your case leading to the disposal of the DbContext.
Asyncrhronous code is multi-threaded behind the scenes. Think of it this way, your web request enters on Thread #1 which creates a DbContext instance via an IoC container, calls an asynchronous method, then returns. When the code calls an async method, it automatically hands that code off to a worker thread to execute. By adding await you tell .Net to create a resume point to come back to. That may be the original calling thread, or a new worker thread, though the important thing is that the calling code will resume only after the async method completes. Without await, there is no resume point, so the calling code continues after the async method call. This can lead to all kinds of bad behaviour. The calling code can end up completing and disposing the DbContext (what you are seeing) or if it calls another operation against the DbContext you could end up with an exception complaining about access across multiple threads since a DbContext detects that and does not allow access across threads.
You can observe the threading behaviour by inspecting Thread.CurrentThread.ManagedThreadId before the async method call, inside the async method, then after the async method call.
Without the await you would see Thread #X before the method call, then Thread #Y inside the async method, then back to Thread #X after. While debugging it would most likely appear to work since the worker thread would likely finish by the time you were done with the breakpoints, but at runtime that worker thread (Y) would have been started, but the code after the call on thread X would continue running, ultimately disposing of your DbContext likely before Thread Y was finished executing. With the await call, you would likely see Thread #X before the method call, Thread #Y inside, then Thread #Z after the call. The breakpoint after the async call would only be triggered after the async method completes. Thread #X would be released while waiting for the async method, but the DbContext etc. wouldn't be disposed until the resumption point created by awaiting the async method had run. It is possible that the code can resume on the original thread (X) if that thread is available in the pool.
This is a very good reason to follow the general naming convention for asynchronous methods to use the "Async" suffix for the method name. If your Mediator.Send method is async, consider naming it "SendAsync" to make missing await statements a lot more obvious. Also check those compiler warnings! If your project has a lot of warnings that are being ignored, this is a good reason to go through and clean them up so new warnings like this can be spotted quickly and fixed. This is one of the first things I do when starting with a new client is look at how many warnings the team has been ignoring and pointing out some of the nasty ones they weren't aware were lurking in the code base hidden by the noise.

Spring component with method invoked by several threads

I have the following component which is used by multiple threads since it is being invoked by a listener (Kafka consumer).
#Component
public class SampleClass {
private RuleFactory ruleFactory;
public SampleClass(RuleFactory ruleFactory) {
this.ruleFactory = ruleFactory;
}
void sampleFunction(final SampleObject sampleObject) {
ruleFactory
.getRules().stream()
.filter(ruleFilter -> ruleFilter.getPredicate().test(sampleObject))
.findFirst()
.ifPresent(caseWinner -> caseWinner.applyChanges().accept(sampleObject));
}
}
The method doesn't change the state of the class, but is shares another component the RuleFactory. Which doesn't have any mutable attributes.
Is this method thread safe ? An answer I got, was, it is not since you apply changes to an object which is passed as a parameter. Is this valid?
I can't think of any case other than two threads passing the same object and process it in parallel.
Should this method be synchronized? Is this final keyword useless in terms of thread safety?
The method is thread-safe if all of the following are true:
All of the ruleFactory methods called are thread safe, that is, none of them change internal state of ruleFactory.
ruleFilter and caseWinner are thread-safe
If another thread has a reference to sampleObject, then the state of sampleObject must not be modified.
You already said RuleFactory is thread safe.
If you modify sampleObject in this function and if another thread has reference to sampleObject, then there is a race condition. Synchronizing this function will only work if all the other threads are using the method of the same SampleClass instance to modify sampleObject. You can use sampleObject itself, but you have to make sure all other threads that access to sampleObject also use synchronize blocks:
synchronized(sampleObject) {
// read or write sampleObject
}

NetworkStream ReadAsync and WriteAsync hang infinitelly when using CancellationTokenSource - Deadlock Caused by Task.Result (or Task.Wait)

After reading pretty much every question on Stack Overflow and Microsoft's documentation about NetworkStream, I dont understand what is wrong with my code.
The problem I see is that my method GetDataAsync() hangs very often. I call this method from Init Method like so:
public MyView(string id)
{
InitializeComponent();
MyViewModel myViewModel = session.Resolve<MyViewModel>(); //Autofac
myiewModel.Init(id);
BindingContext = myViewModel;
}
Above, my View does its initialization, then resolves MyViewModel from Autofac DiC and then calls MyViewModel Init() method to do some additional setup on the VM.
The Init method then calls my Async method GetDataAsync which return a IList like so:
public void Init()
{
// call this Async method to populate a ListView
foreach (var model in GetDataAsync("111").Result)
{
// The List<MyModel> returned by the GetDataAsync is then
// used to load ListView's ObservableCollection<MyModel>
// This ObservableCollection is data-bound to a ListView in
// this View. So, the ListView shows its data once the View
// displays.
}
}
, and here is my GetDataAsync() method including my comments:
public override async Task<IList<MyModel>> GetDataAsync(string id)
{
var timeout = TimeSpan.FromSeconds(20);
try
{
byte[] messageBytes = GetMessageBytes(Id);
using (var cts = new CancellationTokenSource(timeout))
using (TcpClient client = new TcpClient(Ip, Port))
using (NetworkStream stream = client.GetStream())
{
await stream.WriteAsync(messageBytes, 0, messageBytes.Length, cts.Token);
await stream.FlushAsync(cts.Token);
byte[] buffer = new byte[1024];
StringBuilder builder = new StringBuilder();
int bytesRead = 0;
await Task.Delay(500);
while (stream.DataAvailable) // need to Delay to wait for data to be available
{
bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cts.Token);
builder.AppendFormat("{0}", Encoding.ASCII.GetString(buffer, 0, bytesRead));
}
string msg = buffer.ToString();
}
return ParseMessageIntoList(msg); // parses message into IList<MyModel>
}
catch (OperationCanceledException oce)
{
return await Task.FromResult<IList<RoomGuestModel>>(new List<RoomGuestModel>());
}
catch (Exception ex)
{
return await Task.FromResult<IList<RoomGuestModel>>(new List<RoomGuestModel>());
}
}
I would expect that a ReadAsync or WriteAsync either complete successfully, throw some exception, or get cancelled after 10 seconds in which case I would catch OperationCanceledException.
However, it just hangs endlessly when I call method above. If I am debugging and have some breakpoints in the code above, I will be able to go through the method entirely but if I call it 2nd time, app just hangs forever.
I am new to Tasks and Async programming, so I am also not sure I do my cancellations and exception handling properly here?
UPDATE AND FIX
I figured out how to fix the deadlock issue. In hope this will help others sho might run into the same issue, I'll first explain it. The articles that helped me a lot are:
https://devblogs.microsoft.com/pfxteam/await-and-ui-and-deadlocks-oh-my/ by Stephen Taub
https://montemagno.com/c-sharp-developers-stop-calling-dot-result/ by James Montemagno
https://msdn.microsoft.com/en-us/magazine/jj991977.aspx by StephenCleary
https://blog.xamarin.com/getting-started-with-async-await/ by Jon Goldberger
#StephenCleary was great help understanding the issue. Calling Result or Wait (above, I call Result when calling GetDataAsync) will lead to dead-lock.
The context thread (UI in this case) is now waiting for GetDataAsync to complete, but GetDataAsync captures the current context-thread (UI thread), so it can resume on it once it gets data from TCP. But since this context-thread is now blocked by call to Result, it cannot resume.
The end result is that it looks like call to GetDataAsync has deadlocked but in reality, it is call to Result that deadlocked.
After reading tons of articles from #StephenTaub, #StephenCleary, #JamesMontemagno, #JoeGoldenberger (thank you all), I started getting understanding of the issue (I am new to TAP/async/await).
Then I discovered continuations in Tasks and how to use them to resolve the issue (thanks to Stephen Taub's article above).
So, instead of calling it like:
IList<MyModel> models = GetDataAsync("111").Result;
foeach(var model in models)
{
MyModelsObservableCollection.Add(model);
}
, I call it with continuation like this:
GetDataAsync(id)
.ContinueWith((antecedant) =>
{
foreach(var model in antecedant.Result)
{
MyModelsObservableCollection.Add(model);
}
}, TaskContinuationOptions.OnlyOnRanToCompletion)
.ContinueWith((antecedant) =>
{
var error = antecedant.Exception.Flatten();
}, TaskContinuationOptions.OnlyOnFaulted);
This seam to have fixed my deadlocking issue and now my list will load fine even though it is loaded from the constructor.
So, this seam to work just fine. But #JoeGoldenberger also suggests another solution in his article https://blog.xamarin.com/getting-started-with-async-await/ which is to use Task.Run(async()=>{...}); and inside that await GetDataAsync and load ObservableCollection. So, I gave that a try as well and that is not blocking either, so working great:
Task.Run(async() =>
{
IList<MyModel> models = await GetDataAsync(id);
foreach (var model in models)
{
MyModelsObservableCollection.Add(model);
}
});
So, it looks like either of these 2 will remove deadlock just fine. And since above my Init method is called from a c-tor; therefore, I cannot make it Async and await on this, using one of the 2 methods described above resolves my problem. I dont know which one is better but in my tests, they do work.
Your problem is most likely due to GetDataAsync("111").Result. You shouldn't block on async code.
This can cause deadocks. E.g., if you're on a UI thread, the UI thread will start GetDataAsync and run it until it hits an await. At this point, GetDataAsync returns an incomplete task, and the .Result call blocks the UI thread until that task is completed.
Eventually, the inner async call completes and GetDataAsync is ready to resume executing after its await. By default, await captures its context and resumes on that context. Which in this example is the UI thread. Which is blocked since it called Result. So, the UI thread is waiting for GetDataAsync to complete, and GetDataAsync is waiting for the UI thread so it can complete: deadlock.
The proper solution is to go async all the way; replace .Result with await, and make the necessary changes to other code for that to happen.
As stated in my update, going async all the way by providing an async lambda like below resolved the issue for me
Task.Run(async() =>
{
IList<MyModel> models = await GetDataAsync(id);
foreach (var model in models)
{
MyModelsObservableCollection.Add(model);
}
});
Loading asynchronously an observable collection in a ctor this way (in my case, ctor calls Init which then uses this Task.Run) solves problem

BeginInvoke method and Session State

I am invoking a asynchronous PageMethod call from the client-side. The backend code is
[WebMethod(EnableSession = true)]
public static string BeginMethodCall()
{ //Session Accessible here
string g = Guid.NewGuid().ToString();
Func<object> f = () => MethodCall();
IAsyncResult asyncCall = f.BeginInvoke(null, f);
lock (AsyncThreadPool)
AsyncThreadPool[g] = asyncCall;
return g;
}
[WebMethod(EnableSession=true)]
public static object EndMethodCall(string guId)
{
IAsyncResult callResult;
lock (AsyncThreadPool)
{
callResult = AsyncThreadPool[guId];
AsyncThreadPool.Remove(guId);
}
Func<object> f = (Func<object>)callResult.AsyncState;
callResult.AsyncWaitHandle.WaitOne();
return f.EndInvoke(callResult);
}
[WebMethod(EnableSession = true)]
public static object MethodCall()
{
//Session not accessible here
}
Session state is accessible from BeginMethodCall() and EndMethodCall() but not from the MethodCall().
Can anyone tell me why I lose my session state here?
Do threads lose the Session context because asyn calls are not thread safe?
Is there a way to access session here?
In case someone may find this useful
BeginXXX does create a new theard and threads are not session safe for obvious reasons
In general,
Session + Async = fail
You're safe within callbacks and before you branch off into async code, but while you're in parallel, you don't get full session state.
However, there are a few workarounds. The easiest of which is
[SessionState(System.Web.SessionStateBehavior.ReadOnly)]
at the controller level, which allows, obviously, read-only access to session values. It'll work in parallel as long as you don't try to write to session. You can also implement your own HttpHandler, but that ones a little tougher.

Subscription to DTE events doesn't seem to work - Events don't get called

I've made an extension inside a package and I am calling the following code (occurs when a user presses a button in the toolbar):
DocumentEvents documentEvents = (DTE2)GetService(typeof(DTE));
_dte.Events.DebuggerEvents.OnEnterBreakMode += DebuggerEvents_OnEnterBreakMode;
_dte.Events.DebuggerEvents.OnEnterDesignMode += DebuggerEvents_OnEnterDesignMode;
_dte.Events.DebuggerEvents.OnContextChanged += DebuggerEvents_OnContextChanged;
_dte.Events.DocumentEvents.DocumentSaved += new _dispDocumentEvents_DocumentSavedEventHandler(DocumentEvents_DocumentSaved);
_dte.Events.DocumentEvents.DocumentOpened += new _dispDocumentEvents_DocumentOpenedEventHandler(DocumentEvents_DocumentOpened);
void DocumentEvents_DocumentOpened(Document Document)
{
}
void DocumentEvents_DocumentSaved(Document Document)
{
}
void DebuggerEvents_OnEnterBreakMode(dbgEventReason Reason, ref dbgExecutionAction ExecutionAction)
{
}
void DebuggerEvents_OnContextChanged(Process NewProcess, Program NewProgram, Thread NewThread, StackFrame NewStackFrame)
{
}
private void DebuggerEvents_OnEnterDesignMode(dbgEventReason reason)
{
}
The first and the major problem is that the subscription to the event doesn't work. I've tried:
Opening new documents
Detaching from debug (thus supposedly triggering OnEnterDesignMode
Saving a document
None of these seem to have any effect and the callback functions were never called.
The second issue is that the subscription to the event line works USUALLY (the subscription itself, the callback doesn't work as described above) but after a while running the subscription line, e.g:
_dte.Events.DebuggerEvents.OnEnterBreakMode -= DebuggerEvents_OnEnterBreakMode;
Causes an exception:
Exception occured!
System.Runtime.InteropServices.InvalidComObjectException: COM object that has been separated from its underlying RCW cannot be used.
at System.StubHelpers.StubHelpers.StubRegisterRCW(Object pThis, IntPtr pThread)
at System.Runtime.InteropServices.UCOMIConnectionPoint.Unadvise(Int32 dwCookie)
at EnvDTE._dispDebuggerEvents_EventProvider.remove_OnEnterDesignMode(_dispDebuggerEvents_OnEnterDesignModeEventHandler A_1)
Any ideas will be welcome
Thanks!
Vitaly
Posting an answer that I got from MSDN forums, by Ryan Molden, in case it helps anyone:
I believe the problem here is how the
CLR handles COM endpoints (event
sinks). If I recall correctly when
you hit the
_applicationObject.Events.DebuggerEvents
part of your 'chain' the CLR will
create a NEW DebuggerEvents object for
the property access and WON'T cache
it, therefor it comes back to you, you
sign up an event handler to it (which
creates a strong ref between the
TEMPORARY object and your object due
to the delegate, but NOT from your
object to the temporary object, which
would prevent the GC). Then you don't
store that object anywhere so it is
immediately GC eligible and will
eventually be GC'ed.
I changed the code to store DebuggerEvents as a field and it all started to work fine.
Here is what #VitalyB means using code:
// list where we will place events.
// make sure that this variable is on global scope so that GC does not delete the evvents
List<object> events = new List<object>();
public void AddEvents(EnvDTE dte)
{
// create an event when a document is open
var docEvent = dte.Events.DocumentEvents;
// add event to list so that GC does not remove it
events.Add(docEvent );
docEvent.DocumentOpened += (document)=>{
Console.Write("document was opened!");
};
// you may add more events:
var commandEvent = dte.Events.CommandEvents;
events.Add(commandEvent );
commandEvent.AfterExecute+= etc...
}

Resources