long running process vb.net - windows

I have a service ticket management application and users want to open several ticket details on a tab in a MDI frame. Since this application has to communicate through Web XML service with other company, it takes around 15 ~20 seconds. The users most complain is that he needs to wait until a saving process is done. Cursor is working while data is being saved and other can't be done.
What is the most effective way to let user open other window and do something else or save data while data is being saved from other windows?
By the way, this is VB.Net / Windows Application.

You could use a BackgroundWorker or new thread. I personally would try using built in asynchronous methods, such as BeginInvoke
http://www.developer.com/net/vb/article.php/1443981/Asynchronous-Web-Services-for-Visual-Basic-NET.htm
Keep in mind that asynchronous operations become complicated very quickly, good desighned in very important.

Use BackgroundWorker ...
Refer to the following:
Manage a background process by using the BackgroundWorker component

I've written a web service which is part of a solution which needs to go off and run a method which takes quite a long while to run through. After some experimenting, I decided it was simplest to kick off the long running task in a new thread within the web service and return a custom object to the calling application (which is then used later).
<WebMethod()> Public Function StartChecks() As ResponseItem
Dim t As New Thread(New ThreadStart(AddressOf Me.StartWork))
t.Start()
Return New ResponseItem(CheckGUID.ToString)
End Function

Related

Running a console app programmatically whenever needed

I have a C# console app that processes a queue (in db) and processes user uploaded contents.
It is running as a scheduled task.
If some user drops some content, the process won't pick it up until it is time for it to run.
If the job runs once every 5 minutes then it has to wait for max 5 minutes to run.
I want to process user content right away.
If user1 drops content and then user2 drops content after 30 seconds, I want 2 instances of my job running.
Is it possible to trigger the job\task to run from the C# code (MVC controller)?
Essentially it sounds like you're just looking to perform an asynchronous operation. Depending on the version of .NET, there are a number of options. For example, the Task Parallel Library is a simple way to invoke an asynchronous operation. So if the task is encapsulated into some object (for the same of example, let's say a method called Process on an object called content) then it might look like this:
var processContent = new Task(() => content.Process());
processContent.Start();
The task would then continue asynchronously and flow control would return to the application (which is particularly ideal in a web application where you don't want a user looking at an unresponsive browser, naturally).
If you're using .NET 4.5, you can also make use of the async and await keywords to perhaps make it a little more clear. At its heart, you're talking about running a process in a separate thread.
This all assumes that the web application and the console application share the same back-end business logic code. Which, of course, is probably what they should be doing. If for some reason that's not an option (and I recommend looking into making it an option), you can start a process from code. It could be something as simple as:
Process.Start("C:\Path\To\ConsoleApplication.exe");
Though forking all of these processes can look pretty messy and might be very difficult to manage in terms of error handling/logging/etc. Another reason why it's best to keep the logic in the same process as the application, just in a separate thread.

Start a background task from a Web Api request

I have an ASP.WEB Web Api controller that needs to fire and forget some slow code. What would be a good way to do that? That is I want the controller to return an HTML response to the browser, while the slow code keeps running somewhere.
Is it a good idea to grab a worker thread from the tread pool and pass in a complex object created by the controller? Or do I need to write a separate windows service to do the work?
Your solution depends on the specifics or your situation and your workload.
You can certainly start of a new task Factory.StartNew when you receive a request.
There is nothing wrong with this technically.
Things you should think about though:
Do I have to return data back to the customer?
This task will use up web server resources so if those tasks take very long time and you get a lot of traffic you may run into situation where your customers are waiting in line to just start being processed. In this situation I think backend server with Windows Service be a much better idea.
All tasks above are subject to IIS Resets. They may be killed during processing your background task.

Can I run Android GeoFencing entirely within a background service?

I have an app which needs almost no user interaction, but requires Geofences. Can I run this entirely within a background service?
There will be an Activity when the service is first run. This Activity will start a service and register a BroadcastReceiver for BOOT_COMPLETED, so the service will start at boot. It's unlikely that this Activity will ever be run again.
The service will set an Alarm to go off periodically, which will cause an IntentService to download a list of locations from the network. This IntentService will then set up Geofences around those locations, and create PendingIntents which will fire when the locations are approached. In turn, those PendingIntents will cause another IntentService to take some action.
All this needs to happen in the background, with no user interaction apart from starting the Activity for the first time after installation. Hence, the Activity will not interact with LocationClient or any location services.
I've actually got this set up with proximityAlerts, but wish to move to the new Geofencing API for battery life reasons. However, I have heard that there can be a few problems with using LocationClient from within a service. Specifically, what I've heard (sorry, no references, just hearsay claims):
location client relies on ui availability for error handling
when called from background thread, LocationClient.connect() assumes that it is called from main ui thread (or other thread with event looper), so connection callback is never called, if we call this method from service running in background thread
When I've investigated, I can't see any reason why this would be the case, or why it would stop my doing what I want. I was hoping it would be almost a drop-in replacement for proximityAlerts...
Can anyone shed some light on things here?
The best thing would be to just try it out, right? Your strategy seems sound.
when called from background thread, LocationClient.connect() assumes that it is called from main ui thread (or other thread with event looper), so connection callback is never called, if we call this method from service running in background thread.
I know this to be not true. I have a Service that is started from an Activity, and the connection callback is called.
I dont know about proximity alerts; but I cant seem to find an API to list my GeoFences. I am worried that my database (sqlite) and the actual fences might get out of sync. That is a design flaw in my opinion.
The reason LocationClient needs UI, is that the device may not have Google Play Services installed. Google has deviced a cunning and complex mechanism that allows your app to prompt the user to download it. The whole thing is horrible and awful in my opinion. Its all "what-if what-if" programming.
(They rushed a lot of stuff out the door for google IO 2013. Not all of it are well documented, and some of it seems a bit "rough around the edges").

how to auto open an entity created in a workflow

I have run into a situation where I need to open a newly created quote at the end of a workflow. I have a feeling this is going to require me to create a a very simple custom workflow that uses "window.open", but I would like to avoid this if anyone has a better idea.
So I need to open a newly created quote as soon as it is created in a workflow. Anyone have any good ideas on how to do this?
Workflows are asynchronous; they run on the server (as opposed to the client) and do not run in realtime. eg a workflow that is triggered by creation of a record will run on the server sometime after the record is created (depending on system load etc - it could be a second or two, or could be half an hour later. If you have stopped the CRM Async service on the server, they might well never run.)
Because they run on the server the user has no interaction with them. As a result you can't open a window, as there's no user involved to open a window for...
What you probably want to do is make use of Dialogs (introduced in CRM 2011). You won't be able to use window.open() but as long as you've got a recent update rollup installed on the server you can present the user with a hyperlink to most CRM records.
Setup of Dialogs is much the same as Workflows, and they use the same mechanics under the hood. The difference is that they're syncronous (i.e. run in real-time) and they are client-side. There's some detail on Technet: http://technet.microsoft.com/en-us/library/gg334463.aspx

How to determine the association between a VB6 app and an exe instanced with CreateObject()

We need to figure out how a service can peek at a running VB6 app and/or its DCOM spawned exe and figure out which VB6 app goes with which DCOM exe. The VB6 app and the spawned exe are both on the same server.
We have a VB6 app that spawns an instance of Bartender (from Seagull Scientific) by way of a CreateObject() call. On a given server, we may have ten or twenty instances of our app, each represents a handheld RF gun client in a warehouse. 95% or more of these VB6 apps will have their own Bartender.
Due to circumstances beyond our control, randomly, one of our VB6 instances will be killed, just as if you killed it using Task Manager. This leaves it's Bartender still alive and consuming resources. After fifty or so have been killed over the course of a few hours or days, these orphaned Bartenders become enough of a resource hog to bring the server to its knees.
We are trying to develop a watcher service to detect which of the Bartenders are still connected, so this new service can kill the orphaned Bartenders. We are trying to accomplish this without changing our VB6 app, but we will modify our app if we have to.
I think this routine, aptly named Who's Your Daddy, might be of use to you. It figures out who spawned the process. It probably won't solve your entire problem, but it's a start.
This is going to be hard, if not impossible, to do. Out-of-process COM components (i.e. ActiveX EXE's) are always started by the COM Service Control Manager, not by the process that called CreateObject. This is why the parent process for the ActiveX EXE is svchost.exe.
Therefore, there is no direct parent-child relationship between the process that calls CreateObject and the process that gets created. Only the remote procedure call (RPC) layer that actually passes method calls back and forth between the two processes knows the identities of the processes involved, but the RPC mechanism is specifically designed to be transparent to the COM subsystem, and there isn't an easy way to get access to this information that I know of.
However, there is a pretty hackish way to handle the orphaned process problem if you are willing to change the VB6 application:
Have your monitor service periodically terminate all running Bartender EXE's (once a day or however often is necessary to prevent the server from slowing down too much).
Write a wrapper DLL for the Bartender functionality, and have your VB6 class use this wrapper library instead of directly instantiating raw Bartender objects. This library would contain a wrapper class that creates a Bartender object, and that has methods that delegate to this object. Each wrapper method should catch error 462 ("The remote server machine does not exist or is unavailable"), recreate the Bartender object if this occurs, and then retry the method.
For example (I haven't actually looked at the Bartender documentation, so this is just demonstrating the idea):
'BartenderWrapper.cls
Private m_bartender As Object
Private Sub Class_Initialize()
Set m_bartender = CreateObject("Bartender.Application")
End Sub
Public Sub PrintLabel(Byval sLabelData As String)
On Error Goto ErrorHandler
m_bartender.PrintLabel sLabelData
Exit Sub
ErrorHandler:
If IsRpcError(Err) Then
Set m_bartender = CreateObject("Bartender.Application")
Resume
End If
Err.Raise Err.Number, Err.Source, Err.Description
End Sub
Private Function IsRpcError(Byval e As ErrObject) As Boolean
IsRpcError = (e.Number = 462)
End Function
The idea here is that since you can't reliably determine which Bartender processes are still connected to an instance of your VB6 application, you can kill all of the running Bartender processes periodically, and your application will still be able to run properly (in most cases), because if you kill a Bartender EXE that was being used by a running instance of your VB6 application, your application will create a new Bartender instance and continue running normally.
This solution definitely isn't fool-proof, and may be hard to implement if you are using a lot of methods or the Bartender instance you create has important internal state that could be lost when creating a new instance.
When it comes down to it, there isn't a clean way to detect orphaned ActiveX EXE's if you don't control all of the applications that are involved (one common solution when you do control the ActiveX EXE is to have the ActiveX EXE raise an event with a ByRef parameter every second or so, and have it shut itself down if the client doesn't change the value of the parameter).
What we have decided to do is to have the client write a hint file each time the Client creates a Bartender. The client writes a tiny XML file in a common folder that says an XML equivalent of "I am PID number n. Between time x and time y, I created a Bartender." The times x and y are timestamps obtained immediately before and after the CreateObject call. We will have a monitor service that watches for new Clients, new Bartenders and hint files. By watching all these, we think we can create small groups or associations of clients and their associated bartenders. In any given group, when all the clients go away, any remaining Bartenders that were in that group can be KILLED!

Resources