08-19-2015 01:20 AM
I have a ASP.NET applicatoin that connects to SAS using the Integration Technologies Pooling. We have the COM Interop wrapper around the SASWorkspaceManager and related COM objects. I have based my code off the examples I found on the SAS documentation that are mostly in VB and translated them to C# for my needs. After the application is running for a little while I start getting an intermittent error saying "The wait time expired before a workspace came available." After doing some testing in our development environment it seems that the issue is that the MaxPerWorkspacePool number is getting reached and then new connections are throwing this error until eventually some of those workspaces go away. Looking at the processes on the server, I see that a sas.exe process is created for each connection and stays there even after the results have been returned. Eventually they go away but it takes a long time, around 10-15 minutes it seems. To me it seems like the pooling is not working because the workspace/process is being held onto maybe and not returned to the pool to be used by the next connection.
I have tried playing around with the ServerDef and LoginDef but have not found a combination that resolves this. I have increased the MaxPerWorkspacePool value for now to make it less likely that it is reached but that is obviously not a long term solution. Below are snippets of my C# code and the values I am currently using for the configuration settings of the WorkspacePool.
Here is my Connect() method which gets called only once on the application startup:
public void Connect()
// This manages the workspace in which we will perform our queries
var workspaceManager = new WorkspaceManager();
// This stores server information
var server = new ServerDef
MachineDNSName = ConfigurationManager.AppSettings["Sas.Server"],
Protocol = Protocols.ProtocolBridge,
Port = Int16.Parse(ConfigurationManager.AppSettings["Sas.Port"]),
//Specifies the maximum number of servers that should be created from the provided ServerDef object. A good starting place for this number is the number of CPUs that are available on the machine that's running SAS.
MaxPerWorkspacePool = 32,
// Specifies the number of times that a Workspace is used before the process it is running in is replaced. This is useful for capping any memory leaks or non-scalable resource usage. A value of 0 means to never recycle the processes.
RecycleActivationLimit = 50,
//The value for this property must be either true or false. If the value is false, then unallocated live connections will be disconnected after a period of time (specified by the value of ServerDef.ShutdownAfter). If the value is true (the default value), unallocated live connections will remain alive indefinitely. This property is optional.
RunForever = false,
// Specifies the number of minutes that an unallocated live connection will wait to be allocated to a user before shutting down. This property is optional and it is ignored if the value of ServerDef.ServerRunForever is true. The value must not be less than 0, and it must not be greater than 1440 (the number of minutes in a day). The default value is 3. If the value is 0, then a connection returned to a pool by a user will be disconnected immediately unless another user is waiting for a connection from the pool.
ShutdownAfter = 0
// This stores login information for the server
var login = new LoginDef
LoginName = ConfigurationManager.AppSettings["Sas.Username"],
Password = ConfigurationManager.AppSettings["Sas.Password"],
// Specifies the minimum number of Workspaces using this LoginDef that are created when the pool is created.
MinSize = 0,
// Specifies the minimum number of Workspaces using this LoginDef that need to be available. Note that MaxPerWorkspacePool will never be exceeded.
MinAvail = 0
// Create Workspace Pool
// If it does not exist, we will get an error
// In the catch statement, we will then create the application pool
catch (Exception ex)
// Create the object pool
workspaceManager.WorkspacePools.CreatePoolByServer("MyPool", server, login);
Code that runs the SAS script is here:
var workspaceManager = new WorkspaceManager();
var workspacePool = workspaceManager.WorkspacePools.Item("MyPool");
var pooledWorkspace = workspacePool.GetPooledWorkspace("", "", 2000);
var workspace = pooledWorkspace.Workspace;
var storedProcessService = workspace.LanguageService.StoredProcessService;
storedProcessService.Repository = "file:\\chis\\code"; // local path on the SAS server
storedProcessService = null;
pooledWorkspace = null;
The documentation shows VB and says that to release the pooled workspace you just set it to nothing or leave the scope, so it seems to me that it should be released based on the code above, but it doesn't appear to be functioning that way. But I am most likely missing something.
I am not sure where to go from here, whether this is a server configuration issue, a code issue or maybe a SAS script issue. Any thoughts would be greatly appreciated.egration