I have an existing service that notifies a large number of clients when an event occurs. It uses a long polling mechanism that I rolled myself. I'm exploring replacing that mechanism with a signalr hub, and have a prototype working. But it has a pretty significant inefficiency that feels like there should be a solution to, but I'm not finding it.
I understand the idea of groups in signalr, and groups are obviously intended to prevent this inefficiency, but there is a reason that I cannot use groups. I hope it suffices to say that I need to call the same client method, with the same parameter values, on many clients using each client's ConnectionId. I can explain why if necessary, but it's really beside the point.
Assume I have a list of 200 ConnectionId's and I need to call the same method on each of them passing the same object parameter. If I simply iterate through the ConnectionId's calling Clients.Client(ConnectionId).clientMethod(param), I presume that the param object would be serialized 200 times.
Is there a way to serialize the parameter(s) one time, then invoke the client method using the already-serialized parameters?
UPDATE
I've found a github issue that sounds related (maybe even this exact issue) at Allow to Send Json Strings without duplicate Serialization. It appears that the functionality was added to signalr, but the github issue doesn't say anything about how to do it, and I can't find anything regarding it in the signalr docs.
UPDATE 2
In the github issue referenced above, the new functionality was implemented for PersistentConnection only -- not hubs. With persistent connections, when sending a parameter of type ArraySegment, signalr assumes it to be pre-serialized and sends it as-is without serializing it.
For some reason, this was not implemented for hubs, although it would be useful for hubs for the same reason it was useful for persistent connections.
Store all connectionId's in a Static List<string> atOnConnected` event and use the following,
Static List<string> allconnections = new List<string>();
public override Task OnConnected()
{
allconnections.Add(Context.ConnectionId);
return base.OnConnected();
}
Public void YourServerMethod(params)
{
Clients.Clients(allConnections).clientMethod(params)
}
Related
I have a CRUD app in Blazor that simply fetches the assignment lists from a table and has an AssignmentReminderService for data access layer that has a method (async version)
public async Task<AssignmentReminder> AddAssignment(AssignmentReminder assignment)
{
_context.assignments.Add(assignment);
await _context.SaveChangesAsync();
return assignment;
}
I can also call the method with synchromus code as :
public AssignmentReminder AddAssignment(AssignmentReminder assignment)
{
_context.assignments.Add(assignment);
_context.SaveChanges();
return assignment;
}
Now it is just one database being accessed from a local server(could be hosted on cloud as well) with just one assignment table and the default authentication/authorization tables generated when one uses Individual User Account (aspnetusers, aspnetroles etc)
Can someone let me know which of the two ways I should use (between async or sync) method declaration?
In the general case, you should use asynchronous APIs if they are available. This will result in greater scalability on the server side, since asynchrony will allow the calling request thread to be used for other requests while the asynchronous operation is in progress.
There are specific scenarios where this guideline doesn't apply. E.g., if you're calling a generic asynchronous API (like Stream.ReadAsync) but you know that the implementation is actually synchronous (like MemoryStream). But in general, if there's an asynchronous API, then that's the one you should use.
You should be clear about the version of blazor you're talking about, because using async methods in the client is different from using them in the server version.
which of the two ways I should use (between async or sync) method declaration?
The first one.
The scarce resource here are the Threads. You want to keep their number down, and the first approach enables that by releasing the Thread to do other work.
In the second approach the Thread is suspended for the duration of the I/O operation. You would need more Threads to handle the same number of requests.
So using async I/O lets the same hardware handle more requests at the same time.
We currently have third-party software that we use to extract information from.
We use their SDK to send and receive request and noted that the request aren't always accurate. After troubleshooting and reading (not well documented) documentation we realised that the SDK can only receive and send one request at a time.
This causes a issue for us as we are using an ASP.Net web application to access the SDK which means that we have multiple clients that access the SDK at the same time and send multiple request. What the SDK does is if it get a new request while busy with a current request it discards the current request and continues with the new request.
I would like to find out what would be the best way of creating a queuing system for the requests.
I was thinking of creating a WCF service and set the instancecontexctmode to single so that there is only one instance of the service running. Then setting the ThreadPool max threads to 1 and using it to queue the functions so that there is only one active call to the SDK at a time. Although I do not know much about ThreadPool queuing the solution should work.
Here is what I have in mind
Public Sub Sub1(var As String)
'Do work
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf Function1), "Text")
End Sub
Public Function Function1(var As String) As DataTable
'Do Work
Return DataTable
End Function
Sub New()
ThreadPool.SetMaxThreads(1, 1)
End Sub
How would I create the queueing using ThreadPool or is there another way to accomplish the same result?
Will the web application wait for a response from the service?
Update 1
I found another way while fiddling with some code
If I specify the InstanceContextMode must be single and the the function's ReleaseInstanceMode to AfterCall this blocks any other functions from executing while the function is busy. It uses instance deactivation (Details found here)
<ServiceBehavior(InstanceContextMode:=InstanceContextMode.Single)>
Public Class Service1
<OperationBehavior(ReleaseInstanceMode:=ReleaseInstanceMode.AfterCall)>
Public Function DoWork() As String
Return WorkDone
End Function
End Class
Will this work and is there any specific problems that I could run into?
If I was you I would prefer to make one more abstraction, as you can control restriction third party component.
You can inherit third party class (if it's a class) and organize queue inside. Use it as a singleton. Singleton
Using tasks and task factory with limited threads (very similar to your idea): Scheduler
Your idea with ThreadPool.
In case it's a service, the easiest way is to create your own WCF service which will be responsible for queueing, which can be organized by WCF: Throttling
I'm developing an app with VS2013, using EF6.02, and Web API 2. I'm using the ASP.NET SPA template, and creating a RESTful api against an entity framework data source backed by a sql server. (In development, this resides on the SQL Server local instance.)
I've got two API methods so far (one that just reads data, one that writes data), and I'm testing them by calling them in the javascript. When I only call a single method in my script, either one works perfectly. But if I call both in script (without waiting for either's callback to fire), I get bad results and different exceptions in the debugger. Some exceptions state that the save can't be completed because there are pending transactions. Another exception stated something about a conflict with other threads. And sometimes, the read operation fails with a null pointer exception when trying to read a result set.
"New transaction is not allowed because there are other threads running in the session."
This makes me question if I'm correctly getting a new DBContext per request. My code for this looks like:
static Startup()
{
context = new Data.SqlServer.AppDbContext();
...
}
and then whenever instantiating a unit of work, I access Startup.context.
I've tried to implement the unit of work pattern, and each request shares a single UOW object which has a single DBContext object.
My question: Do I have additional responsibility to ensure that web requests "play nicely" with eachother? I hope that this is a problem that others have already dealt with. Perhaps the errors that I'm seeing are legitimate in the sense that if one user's data is being touched, it is temporarily in an invalid state and if other requests come in at that exact moment, they indeed will fail (and I should code anticipating these failures). I guess that even if each request has its own DBContext, they still share the same underlying SQL data source so perhaps that's causing issues.
I can try to put together a testcase, but I get differing behavior depending on where I put breakpoints and how long I spend on them, reaffirming to me that this is timing related.
Thanks for any help or suggestions...
-Ben
Your problem is where you are setting your context. The Startup method is for when the entire application starts, thus any request made will all use the same context. This is not a per request setup, but rather a per application setup. As to why you are getting the errors, EntityFramework is NOT thread-safe. Since IIS spawns many threads to handle concurrent request, your single context is being used across multiple threads.
As for a solution, you can look into
-Dependency Injection frameworks (such as Ninject or Unity)
-place a using statement in your UnitOfWork classes
using(var context = new Data.SqlServer.AppDbContext()){//do stuff}
-Or, I have seen instances of people creating a class that gets the context for that request and stores it in the HttpContext.Cache[] element (using a unique name so you can retrieve it in another class easily), making it so that you will reuse the same context for the same request. Something like this:
public AppDbContext GetDbContext()
{
var httpContext = HttpContext.Current;
if (httpContext == null) return new AppDbContext();
const string contextTypeKey = "AppDbContext";
if (httpContext.Items[contextTypeKey] == null)
{
httpContext.Items.Add(contextTypeKey, new AppDbContext());
}
return httpContext.Items[contextTypeKey] as AppDbContext;
}
To use the above method, make a simple call var context = GetDbContext();
Note
We have all of the above methods, but this is specifically to the third method. It seems to work well with two caveats. First, do not use this in a using statement as it will not be available to any other classes during the scope of the request (you dispose it). And secondly, ensure that you have a call on Application_EndRequest that does actually dispose of it. We saw these little buggers hanging around after the request ended in memory causing a huge spike in memory usage.
I have a web service that receives requests from users and returns some json. I need to save the json string in the database so for the moment, the write query occurs before the response is sent back.
Is there a way to send the response first and then do the write query, after the response left the web service?
Thanks.
There's a couple of different options here - they all have tradeoffs, though, and would be pretty esoteric. You don't mention why you want to do this, so I'm guessing performance. If that's the case, I think you're barking up the wrong tree - a simple write is almost certainly not your performance problem.
So, off the top of my head:
Queuing, as Ragesh mentions, would be a nice approach. This gets you similar semantics of a transaction, while off loading the write. You still have to write to the queue, though, which may be about the same overhead as writing to the DB.
You could spawn a new thread (using either the ThreadPool or System.Threading.Thread - there's some debates about which is preferable in ASP.NET) to handle the write. This can generally work, but you may have issues with unhandled exceptions, app domain restarts, etc.
You could store the JSON data into a static or Application variable, then use a Timer to periodically write them to the DB. This will be multithreaded code, so you will need to synchronize read/writes to the collection.
Similar to #3, store the JSON data into Cache and use the invalidation callback to write to the DB.
Lots of variations on store somewhere (memory, disk, flat DB table, etc.), process later (ASP.NET, scheduled task, Windows Service, Sql Agent, etc.).
#frenchie says: a response starts by reading the json string from the db and ends with writing it back. In other words, if the user sends a request, the json string that's going to be read must be the one that was written in the previous response.
That complicates things, since inherent in async work is not knowing when something is done. If you require the async portion (writing back to the DB) to be done before handling the next request, you'll have to execute a wait to make sure it actually completed. In order to do that, you'll need to keep server side state on the client - not exactly a best practice as far as services go (though, it sounds like you're already doing that with these JSON request/response pairs).
Given the complications, I would make sure that you've done your profiling and determined it is indeed a performance problem.
You can do schedule a query work like
ThreadPool.QueueUserWorkItem(state =>
this.AsynchronousExecuteReference());
// and run
static void AsynchronousExecuteReference()
{
// run here your sql update
}
One other example using Thread inside an class and you can pass parameters to it.
public class RunThreadProcess
{
// Some parametres
public int cProductID;
// my thread
private Thread t = null;
// start it
public Thread Start()
{
t = new Thread(new ThreadStart(this.work));
t.IsBackground = true;
t.SetApartmentState(ApartmentState.MTA);
t.Start();
return t;
}
// actually work
private void work()
{
// do thread work
all parametres are available here
}
}
And here is how I run it
var OneAction = new RunThreadProcess();
OneAction.cProductID = 100;
OneAction.Start();
Do not worry about memory, CG knows that this process is used until the thread ends, so I have check it and CG not delete it and wait the thread to ends.
You should look at using message queues like MSMQ, ActiveMQ or RabbitMQ to do this. When you receive your request, you'll put the relevant data in to the queue, and send your response to the client. At the other end of the queue, you'll have some process that reads from the queue and inserts data in to your database.
this is missing the point of a request/response. unless you want to get into async commands like a service bus, but that's pub/sub, not request/response. the point of request/response is to do the work on the server after receiving the request and before sending the response. even if the work is sending an async message to a service bus.
You could try moving your web service URL to an ASPX page where the lifecycles come in to play.
In the code-behind, call your routine that does the main portion of the work in Page_Load or Page_Prerender (or whenever is appropriate prior to the response being sent) and then do your DB work in the Page_Unload event which occurs after the response has been sent (http://msdn.microsoft.com/en-us/library/ie/ms178472.aspx).
I am creating a node.js module which communicates with a program through XML-RPC. The API for this program changed recently after a certain version. For this reason, when a client is created (createClient) I want to ask the program its version (through XML-RPC) and base my API definitions on that.
The problem with this is that, because I do the above asynchronously, there exists a possibility that the work has not finished before the client is actually used. In other words:
var client = program.createClient();
client.doSomething();
doSomething() will fail because the API definitions have not been set, I imagine because HTTP XML-RPC response has not returned from the program.
What are some ways to remedy this? I want to be able to have a variable named client and work with that, as later I will be calling methods on it to get information (which will be returned via a callback).
Set it up this way:
program.createClient(function (client) {
client.doSomething()
})
Any time there is IO, it must be async. Another approach to this would be with a promise/future/coroutine type thing, but imo, just learning to love the callback is best :)