Edit: Another note: This bug locks up my entire system and kills all open connections (web browser, database connections). Basically a system wide lock up until I do "end program" on the console app. Edit: Yet another note. I am currently running the code on 3 other machines. 1 is a compiled application, the other two are running from the VS2010 IDE under Debug mode. Not one of them has crashed yet. I am starting to think this might be something unique to my system. I'm not sure where to start looking though...
Last Edit for today: I think I may have stumbled upon something... I have been using System.Threading.Timer like this
_MyTimer.Change(Timeout.Infinite, Timeout.Infinite);
//Do some stuff
_MyTimer.Change(5000,5000);
I didn't realize I was setting the re-entrant time in the second parameter. Perhaps this could be the cause of all this mess?
Is there any danger in the following? I'm trying to track down what I think might be a race condition. I figured I'd start with this and go from there.
private BlockingCollection<MyTaskType>_MainQ = new BlockingCollection<MyTaskType>();
private void Start()
{
_CheckTask = new Timer(new TimerCallback(CheckTasks), null, 10, 5000);
}
private void CheckTasks(object state)
{
_CheckTask.Change(Timeout.Infinite, Timeout.Infinite);
GetTask();
_CheckTask.Change(5000,5000);
}
private void GetTask()
{
//get task from database to object
Task.Factory.StartNew( delegate {
AddToWorkQueue(); //this adds to _MainQ which is a BlockingCollection
});
}
private void AddToWorkQueue()
{
//do some stuff to get stuff to move
_MainQ.Add(dataobject);
}
edit: I am also using a static class to handle writing to the database. Each call should have it's own unique data called from many threads, so it is not sharing data. Do you think this could be a source of contention?
Code below:
public static void ExecuteNonQuery(string connectionString, string sql, CommandType commandType, List<FastSqlParam> paramCollection = null, int timeout = 60)
{
//Console.WriteLine("{0} [Thread {1}] called ExecuteNonQuery", DateTime.Now.ToString("HH:mm:ss:ffffff"), System.Threading.Thread.CurrentThread.ManagedThreadId);
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(sql, connection))
{
try
{
if (paramCollection != null)
{
foreach (FastSqlParam fsqlParam in paramCollection)
{
try
{
SqlParameter param = new SqlParameter();
param.Direction = fsqlParam.ParamDirection;
param.Value = fsqlParam.ParamValue;
param.ParameterName = fsqlParam.ParamName;
param.SqlDbType = fsqlParam.ParamType;
command.Parameters.Add(param);
}
catch (ArgumentNullException anx)
{
throw new Exception("Parameter value was null", anx);
}
catch (InvalidCastException icx)
{
throw new Exception("Could not cast parameter value", icx);
}
}
}
connection.Open();
command.CommandType = commandType;
command.CommandTimeout = timeout;
command.ExecuteNonQuery();
if (paramCollection != null)
{
foreach (FastSqlParam fsqlParam in paramCollection)
{
if (fsqlParam.ParamDirection == ParameterDirection.InputOutput || fsqlParam.ParamDirection == ParameterDirection.Output)
try
{
fsqlParam.ParamValue = command.Parameters[fsqlParam.ParamName].Value;
}
catch (ArgumentNullException anx)
{
throw new Exception("Output parameter value was null", anx);
}
catch (InvalidCastException icx)
{
throw new Exception("Could not cast parameter value", icx);
}
}
}
}
catch (SqlException ex)
{
throw ex;
}
catch (ArgumentException ex)
{
throw ex;
}
}
}
per request:
FastSql.ExecuteNonQuery(connectionString, "someProc", System.Data.CommandType.StoredProcedure, new List<FastSqlParam>() { new FastSqlParam(SqlDbType.Int, "@SomeParam", variable)});
Also, I wanted to note that this code seems to fail at random running it from VS2010 [Debug or Release]. When I do a release build, run setup on a dev server that will be hosting it, the application has failed to crash and has been running smoothly.
per request:
Current architecture of threads:
- Thread A reading 1 record from a database scheduling table
- Thread A, if a row is returned, launches a
Task
to login to resource to see if there are files to transfer. The task is referencing an object that contains data from theDataTable
that was creating using a static call. Basically as below. If there are files found,
Task
adds to _MainQ the files to move//Called from Thread A void ProcessTask() { var parameters = new List<FastSqlParam>() { new FastSqlParam(SqlDbType.Int, "@SomeParam", variable) }; using (DataTable someTable = FastSql.ExecuteDataTable(connectionString, "someProc", CommandType.StoredProcedure, parameters)) { SomeTask task = new Task();
void AddFilesToQueue(Task task) { //connect to remote system and build collection of files to WorkItem //e.g, WorkItem will have a collection of collections to transfer. We control this throttling mechanism to allow more threads to split up the work _MainQ.Add(WorkItem); }//assign task some data from dt.Rows[0] if (task != null) { Task.Factory.StartNew(delegate { AddFilesToQueue(task); }); } } }
Do you think there could be a problem returning a value from FastSql.ExecuteDataTable
since it is a static class and then using it with a using
block?