For example, if I have a static
List<int>
object that is manipulated by multi thread, it is not safe to enumerate it without locking it first. When I return the list from a hub method or send it to client, SignalR will internally serialize it without locking it.
In a asp.net core ApiController method I can fully custom serialize it first:
static List<int> list;
object Get()
{
string s;
lock(list)
{
s = JsonConvert.Serialize(list);
}
return new ContentResult(){ Content = s, ContentType = "application/json"};
}
It is not perfect but works.
I have some solutions on it:
Clone the object, before pass it to SignalR.
Disadvantage: Clone is expensive. And deep clone needs more code.
Use Newtonsoft json's callback and error handling. For example:
//the shared object that will return from a hub method
class SomeObject
{
public List<int> list;
[OnSerializing]
internal void OnSerializingMethod(StreamingContext context)
{
Monitor.Enter(this);
}
[OnSerialized]
internal void OnSerializedMethod(StreamingContext context)
{
Monitor.Leave(this);
}
[OnError]
internal void OnError(StreamingContext context, ErrorContext errorContext)
{
Monitor.Leave(this);
}
}
But I'm not sure the OnSerializing
/OnSerialized
and OnSerializing
/OnError
will strictly be called by pair.
- Is
SyncRoot
relate to or solve this problem?