IWorkspaceFactory workspaceFactory = _workspaceFactory.OpenFromString("InvalidConnectionString", 0);
Task<IWorkspace> task = new Task<IWorkspace>(() => { return _workspaceFactory.OpenFromString("InvalidConnectionString", 0); }); if (!task.Wait(10000)) { throw new TimeoutException(); } IWorkspace workspace = task.Result;
IWorkspace workspace = null; Thread thread = new Thread(() => { workspace = _workspaceFactory.OpenFromString("InvalidConnectionString", 0); }); thread.Start(); if (!thread.Join(10000)) { throw new TimeoutException(); }
If an invalid value for a connection string is passed to SDEWorkspaceFactory.OpenFromString(), the call hangs:IWorkspaceFactory workspaceFactory = _workspaceFactory.OpenFromString("InvalidConnectionString", 0);
If I break execution, I can see from the call stack that control is still with the unmanaged code. Unfortunately, this OpenFromString doesn't offer a timeout. What I need to do is, within my .NET managed code, cancel the call to OpenFromString after a certain timeout period. I've tried a couple of approaches, including the following:Task<IWorkspace> task = new Task<IWorkspace>(() => { return _workspaceFactory.OpenFromString("InvalidConnectionString", 0); }); if (!task.Wait(10000)) { throw new TimeoutException(); } IWorkspace workspace = task.Result;
In this case, task.Wait() always returns false, and task.Result() is always null, even if a valid value for the connection string is passed.
I've also tried the following approach:IWorkspace workspace = null; Thread thread = new Thread(() => { workspace = _workspaceFactory.OpenFromString("InvalidConnectionString", 0); }); thread.Start(); if (!thread.Join(10000)) { throw new TimeoutException(); }
In this case, if a valid value for the connection string is passed, execution works as expected, but if an invalid value is passed, the execution still hangs in the unmanaged code, and thread.Join() never returns.
Any suggestions on how to do this?
IWorkspace _workspace; try { var factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.SdeWorkspaceFactory"); var workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType); _workspace = workspaceFactory.OpenFromFile(this.Path, 0); Marshal.ReleaseComObject(workspaceFactory); } catch { throw new BadDatabaseConnectionException("Unable to connect to database"); }
Yes, it hangs indefinitely.
There's no exception thrown.
If the SDEWorkspaceFactory receives an invalid connection string or incomplete connection parameters, it opens up a dialog prompting the user for additional connection parameters. This seems to be a poor design, as it assumes that it will be used in an application in which there will be user interaction. In some cases, there is no interaction, and really an exception should be thrown if there are incomplete connection parameters.
IPropertySet propertySet = new PropertySetClass(); propertySet.SetProperty("SERVER", server); propertySet.SetProperty("INSTANCE", instance); propertySet.SetProperty("DATABASE", database); propertySet.SetProperty("USER", user); propertySet.SetProperty("PASSWORD", password); propertySet.SetProperty("VERSION", version); Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.SdeWorkspaceFactory"); IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType); workspaceFactory.Open(propertySet, 0);
I can't guarantee that the connection method will be OSA; it might be database. I'm relying on clients of my code to provide a valid connection string, so it might be a passage from Finnegans Wake for all I know.
I could write a bunch of code to validate the connection string passed, but my thinking is that this is something that Esri should be checking and returning an error for. Since it doesn't seem that Esri does this, I was hoping to find a way to timeout and throw an exception, rather than having to write and maintain a whole bunch of string validation code.