I am creating a set of classes which interface with a web service. At the core of this, the data is retrieved from the service using an asynchronous NSUrlConnection. In my mind, it is important that it is asynchronous, as a client of these web service interfaces has to have the ability to cancel a request that is in progress (i.e. cancel an NSUrlConnection).
The web service calls return JSON data, potentially lots of it, and this is parsed and the classes I am creating will create proper data structures out of them. Depending on which web service method is called, the request can end up being expensive - too expensive to run on the main thread, so I would like to either add the option of running the service requests asynchronously, or not giving the option, and forcing asynchronous calls.
Async calls are all well and good, but I am having problems starting an NSUrlConnection asynchronously on a runloop that isn't the main one. The problem I'm describing seems to be fairly well documented: I am led to believe the delegate of the NSUrlConnection is not called because the runloop that launches the connection has terminated, and therefore the calls back to the delegate cannot be scheduled on its runloop.
What is the best way to go about solving this issue?
I have tried using:
while (!self.isRequestComplete && !self.isRequestCancelled)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
It seems to work ok from the basic trial I have done, except if the runloop that this is being executed on is actually the main runloop, for which I have had a few crashes...
Would an option be to offer asynchronous calls to clients, and then use the above method if the option is utilised? Is there a better way of achieving what I am trying to do?
What I am aiming to achieve is for a package of classes that allow interfacing with my specific web service, where the clients of my code do not need to worry about whether their own delegates (which my classes hold references to) will be called on different threads. I want them to be called on the exact same runloop that they called my code on - basically, exactly how NSUrlConnection operates!
Thanks in advance!
Nick
I think you may have "gone up the wrong creek" so to speak. Generally speaking you don't need to worry about run loops unless you are doing something rather odd. It sounds like you need to do some reading on multi-threading, particularly Grand Central Dispatch.
Related
I am creating a new net core 2.2 API for use with a JavaScript client. Some examples in Microsoft have the controller having all async methods and some examples aren't. Should the methods on my API be async. Will be using IIS if this is a factor. An example method will involve calling another API and returning the result whilst another will be doing a database request using entity Framework.
It is best practice to use async for your controller methods, especially if your services are doing things like accessing a database. Whether or not your controller methods are async or not doesn't matter to IIS, the .net core runtime will be invoking them. Both will work, but you should always try to use async when possible.
First, you need to understand what async does. Simply put, it allows the thread handling the request to be returned to the pool to field other requests, if the thread enters a wait state. This is almost invariably caused by I/O operations, such as querying a database, writing/reading a file, etc. CPU-bound work such as calculations require active use of the thread and therefore cannot be handled asynchronously. As side benefit of async is the ability to "cancel" work. If the client closes the connection prematurely, this will fire a cancellation token which can be used by supported asynchronous methods to cancel work in progress. For example, assuming you passed the cancellation token into a call to something like ToListAsync(), and the client closes the connection, EF will see this an subsequently cancel the query. It's actually a little more complex than that, but you get the idea.
Therefore, you need to simply evaluate whether async is beneficial in a particular scenario. If you're going to be doing I/O and/or want to be able to cancel work in progress, then go async. Otherwise, you can stick with sync, if you like.
That said, while there's a slight performance cost to async, it's usually negligible, and the benefits it provides in terms of scalability are generally worth the trade-off. As such, it's pretty much preferred to just always go async. Additionally, if you're doing anything async, then your action should also be async. For example, everything EF Core does is async. The "sync" methods (ToList rather than ToListAsync) merely block on the async methods. As such, if you're doing a query via EF, use async. The sync methods are only there to support certain limited scenarios where there's no choice but to process sync, and in such cases, you should run in a separate thread (Task.Run) to prevent deadlocks.
UPDATE
I should also mention that things are a little murky with actions and particularly Razor Page handlers. There's an entire request pipeline, of which an action/handler is just a part of. Having a "sync" action does not preclude doing something async in your view, or in some policy handler, view component, etc. The action itself only needs to be async if it itself is doing some sort of asynchronous work.
Razor Page handlers, in particular, will often be sync, because very little processing typically happens in the handler itself; it's all in subordinate processes.
Async is very important concept to understand and Microsoft focus too much on this. But sometimes we don't realise the importance of this. Every time you are not using Async you are blocking the caller thread.
Why Use Async
Even if your API controller is using single operation (Let's say DB fetch) you should be using Async. The reason is your server has limited number of threads to handle client requests. Let's assume your application can handle 20 requests and if you are not using Async you are blocking the handler thread to do the operation (DB operation) which could be done by other thread (Async). In turn your request queue grows because your main thread is busy dealing other things and not able to look after new requests , at some stage your application will stop responding. If you would use Async the Main thread is free to handle more client requests while other operation run in the background.
More Resources
I would recommend definitely watching very informative official video from Microsoft on Performance issues.
https://www.youtube.com/watch?v=_5T4sZHbfoQ
The GUI of my program freezes while the program is doing its work. I created a mass import which can send X-thousand datarows via a called webservice into a database. The code is already very big and I cannot rewrite it for multithreading purpose.
I don't know how to do it. Any suggestions? If needed I will show some code, but at the moment I don't know what to show.
Firstly, you should rewrite it to use avoid synchronously doing this on the UI thread. If you do a lot of work on the UI thread, it simply will freeze the UI thread. There are a few options here:
If your web service proxy supports asynchronous calls, and if you're using VB 11, you can use Async / Await to call the web service asynchronously from the UI thread in an asynchronous method, and control will return back to the UI thread at the same point in the asynchronous method when the call has completed. It takes a little while to get your head round asynchrony, but this is probably the best option if it's possible.
You can use the Task Parallel Library to make calls on a different thread, but then you'll need to think carefully about how that thread is going to interact with your UI thread.
You can use BackgroundWorker to run some code on another thread, but report progress and completion back on the UI thread
You could potentially call Application.DoEvents between each web service call, to let the UI handle events. This is dangerous - it can lead to re-entrant code, so locks won't behave as you expect them to, and similar hard-to-diagnose errors. This should be your last option, if all else fails.
I need to implement posting some data to a web server in the background. Just to clarify, by "in the background", I don't mean the normal way of showing a spinning icon and posting data to a web service using something like an AsyncTask or ASIHTTPRequest's [request startAsynchronous] method. I need to maintain a queue of data that a Thread can asychronously start processing and posting to a Web service while the user is working in the application.
I'm looking for some help on designing a queue like that, especially in some edge cases like User receiving a call, logging out of the application while the the post is happening, user leaving the application to goto a different one while a post is happening and the like. How would you handle these cases? Is there any source code you can recommend that does this?
Thanks,
Teja.
I've started using NSOperationQueue in my own work lately, for controlling background network requests. NSOperation deals with most of the boilerplate code necessary for asynchronously running tasks (such as network operations) on threads in the background (or foreground, if necessary for UI updates).
It also allows dependencies across queues; for example, I use two queues in my application:
The first schedules image downloads, at a max concurrency of 2 at a time, in the background. Each image download has a corresponding completion handler (as an NSBlockOperation) that is dependent on the image download completing. These operations sit on the [NSOperationQueue mainQueue], which operates on the main thread, allowing them to update UI (specifically, the corresponding UIImageView).
Note that NSOperation and NSOperationQueue are not for network requests only, but any operation that can be divided into atomic tasks and scheduled concurrently.
Here are Apple's intro docs on the topic.
Having implemented something similar myself, I would recommend using a service and not a thread to do network calls. That way even if your activity gets killed you're sure your network calls will be executed.
Then to implement the queue i suggest you take a look into IntentService (http://developer.android.com/reference/android/app/IntentService.html)
from the docs:
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand. Clients send requests
through startService(Intent) calls; the service is started as needed,
handles each Intent in turn using a worker thread, and stops itself
when it runs out of work.
This "work queue processor" pattern is commonly used to offload tasks
from an application's main thread. The IntentService class exists to
simplify this pattern and take care of the mechanics. To use it,
extend IntentService and implement onHandleIntent(Intent).
IntentService will receive the Intents, launch a worker thread, and
stop the service as appropriate.
All requests are handled on a single worker thread -- they may take as
long as necessary (and will not block the application's main loop),
but only one request will be processed at a time.
If your application is simple enough you can use sendBroadCast() to share info and notifications between your activity and the IntentService
Create a singleton that encapsulate a thread :
In the initialisation of your object :
[NSThread detachNewThreadSelector:#selector(mainPosterThread) toTarget:self withObject:nil];
- (void)mainDownloaderThread
{
if( [NSThread respondsToSelector:#selector(setThreadPriority:)] )
{
[NSThread setThreadPriority:0.1];
}
NSString *urlToDownload = nil;
while(shouldRun)
{
// Take next data to post in a queue (lastObject of a NSArray for example)
if( nextDataToPost )
{
// Post
}
else
{
// Sleep for some time.
}
}
}
You can also have methods for stopping / starting the thread while the app go background / foreground on a multitask supported device. If no multitasking supported, save the post data in the queue at stop time (if not too long) and restore them at start. The biggest chalenge is to manage be able to cancel the current upload while app will ends.
This is an issue which I've been perfecting in every new application I write. Basically I wanted network functionality which is asynchronous and which was written by me using native functionality. I'd be happy to show you some of this code if you're interested.
First of all, I suggest that you make all network calls on the main thread asynchronously rather than synchronously, using a delegate. This way serialization/synchronization/concurrency is not an issue. And since classes are network delegates, I'd just set up one class to where a new connection has a new delegate instance.
[[NSURLConnection alloc] initWithRequest:request delegate:del] autorelease];
e.g.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
Why do the Silerlight-generated WCF proxy class(es) offer only async calls?
There are cases where I don't really need the async pattern (for example in a BackgroundWorker)
EDIT : Sometimes I need to process the results of two WCF calls. It would have been much simpler if I could have waited (the business of the app allows that) for both calls to end and then process.. but noooo.... async! :P
As I understand it, the aim here is to make it hard for people to do the wrong thing (sync. IO from the UI). If you are using the WCF classes, you'll probably have to live with it.
There's actually a technical reason you can't do sync calls, at least from the 'main' browser thread, which is that the browser invokes all the plug-in API calls on the same thread, so if SL were to block that thread while waiting for the network callback, the network callback wouldn't get through and the app would deadlock. That said, the sync API would work fine if initiated from a different thread -- ie, if the application first does a QueueUserWorkItem to get off the browser thread -- but we felt it would be confusing to offer the sync option and have it only work some of the time.
Andrei, there ar emethods that even using the async pattern, allows you write expressive code, esasy to read and maintian, without becoming crazy wating 4 async requests, by just simplifying the way you write your code.
give a look to this library http://syncwcf.codeplex.com/
I understand that it isn't possible/sensible to use threads in RubyCocoa. However it is possible to use asynchronous Cocoa methods to avoid blocking user interface events.
I've successfully used a method on NSURLConnection to send an HTTP request and receive the response without blocking the user interface. But I'm wondering what other asynchronous Cocoa methods like this are available?
Also is it possible/sensible within a RubyCocoa application to use Ruby to spawn separate processes (as opposed to threads)? I suppose one issue would be how to wait for the process to complete, but perhaps this could be done by polling via NSTimer events?
Check this client, it's written in ruby and works pretty well.
httpclient