|
code
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Long process might fail...how to implement a timeout?instantiate an object (third party -- I have no control over it) and then tell it to connect to its data source (again, no control over it). It boils down to just 2 lines of code: Set goSession = New Session goSession.StartOffline sUserId, sPassWord Basically, I have a form built that uses a class from vbaccelerator.com to show an animation, and it keeps going even though those 2 calls can take up to 30 seconds a piece to complete. So, the user is happi(er) because they get more than an hourglass to see that things are working. However, sometimes the call to instantiate the object will fail (after a LONG time, like a few minutes). I know from experience that if it takes longer than 45 seconds, it isn't going to work. So, if that is the case, I'd like to kill all the timers and things on the form and unload it. I tried adding a timer to the form to basically kill everything on the form after 45 seconds, but that event doesn't get fired, running in IDE or compiled, ever. Any ideas on how I can basically simulate (or actually do) 2 processes so that I can kill one if things aren't going to work out? Thanks for any and all ideas, and I didn't explain things correctly, I'll gladly provide more information. Matt "YYZ" <matt.da***@gmail.com> wrote in message Don't suppose you have the code for that 'Session' object eh? Any other way news:1127332810.082269.136310@o13g2000cwo.googlegroups.com... > I've got a situation where in my program, at the start of it, I need to > instantiate an object (third party -- I have no control over it) and > then tell it to connect to its data source (again, no control over it). > > It boils down to just 2 lines of code: > > Set goSession = New Session > goSession.StartOffline sUserId, sPassWord > to predict whether or not it'll fail? Once you make the call, if the Session object doesn't expose 'Cancel' functionality, you're basically at its mercy until it returns. -- Ken Halter - MS-MVP-VB - http://www.vbsight.com DLL Hell problems? Try ComGuard - http://www.vbsight.com/ComGuard.htm Please keep all discussions in the groups.. > Don't suppose you have the code for that 'Session' object eh? No, I dont' have the code. It is a COM obejct created by a company whoalso has a full blown application -- the Session object is just a way to create our own forms and things that can do operations on their database. It's just a way to extend their product and allow customization while still maintaining the integrity of their database. Did that make sense? > Any other way to predict whether or not it'll fail? I can't think of any other way to predict if it will fail, but I'm onlyabout 3 days into using this object. Maybe something will come up later on. I am going to try Someone's suggestion of an activeX exe -- for some reason I had it in my head that I couldn't pass complex objects between them...bad assumption! Matt If you don't have the source for that object(Session), then here is one
solution. VB is not multi threaded so you have to make a work around. One way is to divide it into Client/Server. The client is your current standard EXE, and the server is an ActiveX EXE. This ActiveX EXE takes your request and creates and waits for Session to finish, then notifies your EXE. This ActiveX will have a hidden form and a Timer. You add a reference to this ActiveX EXE to your current project and create a variable that points to it like the following example: Public SessionAgent As clsSessionAgent Set SessionAgent = New clsSessionAgent SessionAgent.StartSession ' This returns immediately t = Timer Do While Abs(Timer - t) > 45 And Not SessionAgent.Done DoEvents ' Or not Loop If Not SessionAgent.Done Then ' Timed out Set SessionAgent = Nothing ' ' Else ' Success Set goSession = SessionAgent.GetSession End If In the ActiveX EXE, the code will look like this: ' In Module1 Public DoStartSession As Boolean Public SessionEstablished As Boolean Public Session1 As Session ' In Form1 Private Sub Timer1_Timer() If DoStartSession Then DoStartSession = False Set Session1 = New Session SessionEstablished = True End If End Sub ' In clsSessionAgent Public Sub StartSession() SessionEstablished = False DoStartSession = True End Sub Public Property Get Done() As Boolean Done = SessionEstablished End Property ' Gets the session after it has been established Public Property Get GetSession() As Session GetSession = Session1 End Property In this setup, the ActiveX EXE will "hang" in the Timer event until Session object is created, leaving your App to do other things. Here are some useful articles that explain some of what I am suggesting: How To Create a DCOM Client/Server Application by Using Visual Basic http://support.microsoft.com/default.aspx?scid=kb;en-us;266717 How To Create a DCOM Client/Server with Events by Using Visual Basic http://support.microsoft.com/default.aspx?scid=kb;en-us;267836 Show quoteHide quote "YYZ" <matt.da***@gmail.com> wrote in message news:1127332810.082269.136310@o13g2000cwo.googlegroups.com... > I've got a situation where in my program, at the start of it, I need to > instantiate an object (third party -- I have no control over it) and > then tell it to connect to its data source (again, no control over it). > > It boils down to just 2 lines of code: > > Set goSession = New Session > goSession.StartOffline sUserId, sPassWord > > Basically, I have a form built that uses a class from vbaccelerator.com > to show an animation, and it keeps going even though those 2 calls can > take up to 30 seconds a piece to complete. So, the user is happi(er) > because they get more than an hourglass to see that things are working. > > However, sometimes the call to instantiate the object will fail (after > a LONG time, like a few minutes). I know from experience that if it > takes longer than 45 seconds, it isn't going to work. So, if that is > the case, I'd like to kill all the timers and things on the form and > unload it. > > I tried adding a timer to the form to basically kill everything on the > form after 45 seconds, but that event doesn't get fired, running in IDE > or compiled, ever. > > Any ideas on how I can basically simulate (or actually do) 2 processes > so that I can kill one if things aren't going to work out? > > Thanks for any and all ideas, and I didn't explain things correctly, > I'll gladly provide more information. > > Matt > > If you don't have the source for that object(Session), then here is one Thanks for that -- like I mentioned to Ken, I didn't realize that an> solution. VB is not multi threaded so you have to make a work around. One > way is to divide it into Client/Server. The client is your current standard > EXE, and the server is an ActiveX EXE. This ActiveX EXE takes your request > and creates and waits for Session to finish, then notifies your EXE. ActiveX EXE can take and return complex objects...I don't know where I got that idea, but it was a bad assumption! Thanks for the advice, and I'll try it out this morning. Matt > Thanks for that -- like I mentioned to Ken, I didn't realize that an You could pass a lot of things. Like stdPicture(Picture1.Picture), ADO's > ActiveX EXE can take and return complex objects...I don't know where I > got that idea, but it was a bad assumption! Recordsets and the data inside it. DCOM takes care of all of this. When you pass something by reference, DCOM transfers the information back and forth. See the following articles which may come in handy later: How To Implement Visual Basic COM Objects Returning Recordsets http://support.microsoft.com/default.aspx?scid=kb;en-us;224424 INFO: Passing ADO Recordsets in Visual Basic Procedures http://support.microsoft.com/default.aspx?scid=kb;en-us;193871 How To Create ADO Disconnected Recordsets in VBA/C++/Java http://support.microsoft.com/default.aspx?scid=kb;en-us;184397 You may want to include GetProcessID method that calls GetCurrentProcessId(), so you could terminate the ActiveX EXE process. However, I don't recommend it. It could destabilize your application, plus it would generate a runtime error like "Method X in Object Y failed". I suspect that you will get an error when you try to release the ActiveX EXE by the following statement or it could take time: Set SessionAgent = Nothing You could instead start a new session with a different variable. Since you are going to run on some strange problems, you may want to look at App object properties and methods that control some aspects of ActiveX projects. Check all properties that begin with OLE. Also, I forgot to mention that you must set Instancing property to SingleUse for clsSessionAgent. I think that it start a new EXE for each object created, but I am not sure. Finally, you may want to study the Coffee2 sample in MSDN. It shows you how to fire an event in a certain client object. The Coffee sample in the other hand(simpler), will fire an event in all client objects "simultaneously". Here is a link to a document about the sample and walkthroughs. You will find the sample files in your MSDN's CD. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vb98/html/vbsmpCoffeeCoffeeCoffee.asp http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon98/html/vbconasynchronouscallbackseventsinking.asp I used Coffee2 sample as a template to allow multiple ActiveX DLL clients to share one DB connection to the database. The ActiveX EXE keeps the connection open 24/7 and responds to clients' requests as long as their is 1 client running. After the last client release the reference, the ActiveX EXE process is unloaded from memory. The drawback from this method is if the ActiveX EXE is executing a long query, the clients have to wait. I solved this in my case by making 2 connections, one is cnSlow(for long queries) and another cnQuick(for a single record). Show quoteHide quote "YYZ" <matt.da***@gmail.com> wrote in message news:1127396219.151336.270620@g14g2000cwa.googlegroups.com... >> If you don't have the source for that object(Session), then here is one >> solution. VB is not multi threaded so you have to make a work around. One >> way is to divide it into Client/Server. The client is your current >> standard >> EXE, and the server is an ActiveX EXE. This ActiveX EXE takes your >> request >> and creates and waits for Session to finish, then notifies your EXE. > > Thanks for that -- like I mentioned to Ken, I didn't realize that an > ActiveX EXE can take and return complex objects...I don't know where I > got that idea, but it was a bad assumption! > > Thanks for the advice, and I'll try it out this morning. > > Matt > Alright, I did what you gave me, and it all works great, except one
thing. It all connects and is all happy, but after I set the active x exe to nothing, then the session variable can't be used anymore. It claims to not be nothing, but yet I can't access even the simplest property on it. Here is a quick little example: <all of your idea above has worked fine, now I'm going to use it> Set goSession = cConn.GetSession() 'All ok to here debug.Print goSession.IsConnected ' Prints True, which is good. Set cConn = nothing debug.print goSession.IsConnected ' Errors out with "Automation Error The remote procedure call failed." I think that when the activex exe ends, then the session object is destroyed. Is this because I'm doing something wrong with the activex exe, or could it be that the session object somehow grabs onto the process id (not sure of terminology here) and then see that the process ended, so it kills itself, even though I have ANOTHER process that wants to keep it alive? My question is really, can this be fixed, do you think, or is this another limitation of the object that I'm using, in which case there is no solution? Matt I got it to work by actually creating the object in the main program,
and then setting the session object in the activex exe to the one I had already created -- creation only takes time the first time after a user starts their computer. Connecting the session is the one that will most likely be the point at which things fail, and your program helps me determine that. Thanks for your help -- looks like that object somehow ties itself to the thread or process that created it, so I can't just pass around references as easily as I'd like. Matt |
|||||||||||||||||||||||