I am sharing a static array between a number of System.Threading.Timer simultaneously. This array is accessed only by the first timer thread & second timer will not accessed this array. An exception is displayed: "error can not evaluate expression a native frame is on top of the call stack in c#"
please reply
project code:
public partial class OPC_server : DevExpress.XtraEditors.XtraForm
{
private System.Threading.Timer timer1;
private System.Threading.Timer timer2;
parameter param = new parameter();//another class
private static readonly object myLockHolder = new object();
private static readonly object myLockHolder1 = new object();
public static OpcServer[] _opcServer;
private void OPC_server_Load(object sender, EventArgs e)
{
getconnectedOPC();
}
public void getconnectedOPC()
{
ds = opcconn.GetOPCServerInfo();
int i=0;
DataTable dtOPC=new DataTable();
if (ds.Tables[0].Rows.Count != 0 || ds.Tables[0] != null)
{
dtOPC = ds.Tables[0].Copy();
_opcServer = new OpcServer[dtOPC.Rows.Count];
TimeSpan delayTime = new TimeSpan(0, 0, 1);
TimeSpan intervalTime = new TimeSpan(0, 0, 0, 0, 450);
foreach (DataRow row in dtOPC.Rows)
{
if (i <= dtOPC.Rows.Count)
{
//connetion(row);
getconnect(i, row, dtOPC.Rows.Count);
i++;
}
}
connetion(dtOPC.Rows.Count);
}
}
//connecting the server
public void getconnect(int conn, DataRow r,int rows)
{
DataSet ds2=new DataSet();
DataTable dt2 = new DataTable();
try
{
string machinename = Convert.ToString(r["OPCIPAddress"]);
string servername = Convert.ToString(r["OPCName"]);
_opcServer[conn] = new OpcServer();
int i = _opcServer[conn].Connect(machinename, servername);
if (i == 0)
{
opcconn.update("true", servername);
writelog(servername, "connected");
}
else
{
opcconn.update("false", servername);
writelog(servername, "disconnected");
}
}
catch (OPCException e)
{
servername = Convert.ToString(r["OPCName"]);
opcconn.update("false", servername);
writelog(servername, e.Message.ToString());
}
catch (ApplicationException e)
{
servername = Convert.ToString(r["OPCName"]);
opcconn.update("false", servername);
writelog(servername, "No instance server");
}
}
public void connetion(object state)
{
int k ,i,q=0;
k = (System.Int32)state;
DataSet dsgroup=new DataSet();
while(j < k)
{
try
{
bool val;
HRESULTS re;
SrvStatus status;
DateTime dt;
i = _opcServer[j].GetStatus(out status);
if (HRESULTS.Failed(i))
{
try
{
opcconn.update("false", _opcServer[j].ServerName.ToString());
string IP = opcconn.search(_opcServer[j].ServerName.ToString());
_opcServer[j].Connect(IP, _opcServer[j].ServerName.ToString());
opcconn.update("true", _opcServer[j].ServerName.ToString());
j++;
}
catch
{
opcconn.update("false", _opcServer[j].ServerName.ToString());
j++;
}
}
else
{
val = HRESULTS.Succeeded(i);
dsgroup = grpclass.getgroupinfo(j + 1);
if (dsgroup.Tables[0].Rows.Count != 0)
{
grpdt = new DataTable();
grpdt = dsgroup.Tables[0].Copy();
foreach (DataRow Row in grpdt.Rows)
{
if (groupcnt <= 128)
{
if (cntgroup < grpdt.Rows.Count)
{
grp = _opcServer[j].AddGroup((Convert.ToString(Row["GroupName"])), (Convert.ToBoolean(Row["setactive"])), (Convert.ToInt32(Row["refreshRate"])), 1);
ds1 = param.getparameter1(Convert.ToInt32(Row["groupID"]));
if (ds1.Tables[0].Rows.Count != 0)
{
dt1 = ds1.Tables[0].Copy();
int tq = 0;
item1 = new OPCItemDef[dt1.Rows.Count];
int clienthandle = 1;
foreach (DataRow r in dt1.Rows)
{
if (tq < item1.Length)
{
item1[tq] = new OPCItemDef(Convert.ToString(r["param_ID"]), Convert.ToBoolean(r["active"]), clienthandle, VarEnum.VT_EMPTY);
++clienthandle;
tq++;
}
}
int y = grp.AddItems(item1, out addRslt);
// thread started like each group assign one thread
OPCthread(Row, groupcnt);
groupcnt++;
cntgroup++;
}
}
}
}
}
cntgroup = 0;
j++;
}
}
catch (OPCException)
{
string servername = opcconn.getserver(j + 1);
string IPadd = opcconn.search(servername);
_opcServer[j].Connect(IPadd, servername);
}
catch (IndexOutOfRangeException)
{
j = 0;
}
catch (InvalidCastException e)
{
try
{
// writelog1(_opcServer[j].ServerName.ToString(), "disconnected");
opcconn.update("false", _opcServer[j].ServerName.ToString());
string IP = opcconn.search(_opcServer[j].ServerName.ToString());
_opcServer[j].Connect(IP, _opcServer[j].ServerName.ToString());
opcconn.update("true", _opcServer[j].ServerName.ToString());
j++;
}
catch
{
// writelog1(_opcServer[j].ServerName.ToString(), "connection failed");
opcconn.update("true", _opcServer[j].ServerName.ToString());
j++;
}
}
catch (ArgumentOutOfRangeException)
{
j = 0;
}
catch (NullReferenceException)
{
try
{
// writelog1("server'" + j + "' ", "no server instance");
OPC1 = opcconn.getserver(j + 1);
string IPA = opcconn.search(OPC1);
_opcServer[j].Connect(IPA, OPC1);
opcconn.update("true", OPC1);
writelog(OPC1, "connected");
j++;
}
catch (OPCException e)
{
opcconn.update("false", OPC1);
writelog(OPC1, e.Message.ToString());
j++;
}
catch (ApplicationException e)
{
opcconn.update("false", OPC1);
writelog(OPC1, "No instance server");
j++;
}
}
}
}
public void OPCthread(DataRow r2,int timerinfo)
{
if (timerinfo == 0)
{
int rer = Convert.ToInt32(r2["refreshRate"]);//at least 1 second
TimeSpan dueTime = new TimeSpan(0, 0,0,0,rer);
TimeSpan interval = new TimeSpan(0, 0, 0 ,0 ,rer);
timer1 = new System.Threading.Timer(register, r2, dueTime,interval);
}
else if (timerinfo == 1)
{
TimeSpan dueTime;
TimeSpan interval;
int rer1 = Convert.ToInt32(r2["refreshRate"]);
dueTime = new TimeSpan(0, 0, 0, 0, rer1);
interval = new TimeSpan(0, 0, 0, 0, rer1);
timer2 = new System.Threading.Timer(register1, r2, dueTime, interval);
}
}
public void register(object row1)
{
try
{
lock (myLockHolder)
{
int cnt = 0, cnt1 = 0;
ItemValue[] rVals;
OPCItemDef[] item;
OpcServer srv = new OpcServer();
string[] array;
//SrvStatus status1;
DataSet paramds = new DataSet();
DataTable paramdt = new DataTable();
DataRow dt = (System.Data.DataRow)row1;
int serverID = Convert.ToInt32(dt["OPCServerID"]);
paramds = param.getparameter(Convert.ToInt32(dt["groupID"]));
if (Convert.ToBoolean(dt["setactive"]) == true)
{
if (paramds != null && paramds.Tables[0].Rows.Count != 0)
{
paramdt = paramds.Tables[0].Copy();
int tq = 0;
item = new OPCItemDef[paramdt.Rows.Count];
int clienthandle = 1;
foreach (DataRow r in paramdt.Rows)
{
if (tq < item.Length)
{
item[tq] = new OPCItemDef(Convert.ToString(r["param_ID"]), Convert.ToBoolean(r["active"]), clienthandle, VarEnum.VT_EMPTY);
++clienthandle;
tq++;
}
}
array = new string[item.Length];
cnt1 = 0;
while (cnt1 < array.Length)
{
array[cnt1] = item[cnt1].ItemID;
cnt1++;
}
rVals = _opcServer[serverID - 1].Read(array, Convert.ToInt32(dt["refreshRate"]));
//this line i got the exception when i checking the value of the _opcserver varible in locals the it will be display as "error can not evaluate expression a native frame is on top of the call stack in c#" & thread will stop the execution.
param.update(rVals, Convert.ToInt32(dt["groupID"]));
}
}
}
}
catch (ThreadAbortException) { }
finally { }
}
public void register1(object row2)
{
try
{
lock (myLockHolder1)
{
int cnt = 0, cnt11 = 0;
ItemValue[] rVals1;
OPCItemDef[] item1;
OpcServer srv1 = new OpcServer();
string[] array1;
DataSet paramds1 = new DataSet();
DataTable paramdt1 = new DataTable();
DataRow dt1 = (System.Data.DataRow)row2;
int serverID1 = Convert.ToInt32(dt1["OPCServerID"]);
// Boolean gstatus = grpclass.getstatus(Convert.ToInt32(dt["groupID"]));
paramds1 = param.getparameter2(Convert.ToInt32(dt1["groupID"]));
if (Convert.ToBoolean(dt1["setactive"]) == true)
{
if (paramds1 != null)
{
paramdt1 = paramds1.Tables[0].Copy();
int tq1 = 0;
item1 = new OPCItemDef[paramdt1.Rows.Count];
int clienthandle1 = 1;
foreach (DataRow r in paramdt1.Rows)
{
if (tq1 < item1.Length)
{
item1[tq1] = new OPCItemDef(Convert.ToString(r["param_ID"]), Convert.ToBoolean(r["active"]), clienthandle1, VarEnum.VT_EMPTY);
clienthandle1++;
tq1++;
}
}
array1 = new string[item1.Length];
cnt11 = 0;
while (cnt11 < array1.Length)
{
array1[cnt11] = item1[cnt11].ItemID;
cnt11++;
}
rvals = _opcServer[serverID1 - 1].Read(array1, Convert.ToInt32(dt1["refreshRate"]));//this line i got the exception when i checking the value of the _opcserver varible in locals the it will be display as "error can not evaluate expression a native frame is on top of the call stack in c#" & thread will stop the execution.
param.update1(rVals1, Convert.ToInt32(dt1["groupID"]));
}
}
}
}
catch { }
finally { }
}
The error you are seeing is not an Exception. The message you see is just letting you know that a native frame is on the top of the stack instead of a managed frame.
It's possible that the error you're seeing has nothing to do with the array - but it's difficult to tell without seeing some of your code.
There are two very common problems involved with multi-threaded programs. If I had to take a guess, you're getting an InvalidOperationException either because the "Object is currently in use" or because "Cross-thread operation not valid".
If the first is the case, you need to use something like:
lock (myObject)
{
// Alter myObject
}
see Locks.
And if the second is the case, you need to use something like:
Invoke(new MethodInvoker(delegate()
{
// Alter stuff in Forms/Controls
}));
see Invoke.
It would really help if you could post the exact Exception you're getting and the code which produces it.
Edit: You have posted a mountain of code to look through. It is very unhelpful.
You say the line causing it is
rvals = _opcServer[serverID1 - 1].Read(array1, Convert.ToInt32(dt1["refreshRate"]));
but nowhere in your code can I see you have declared the variable _opcServer.
As I have already told you, the native frame message isn't an Exception and doesn't mean that there is anything wrong with your program! - it's simply the debugger telling you that it can't give you the values of the managed variables.
Please put this code around the line to identify which type of Exception you are getting, and tell me what the Exception is.
try
{
rvals = _opcServer[serverID1 - 1].Read(array1, Convert.ToInt32(dt1["refreshRate"]));
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show("Exception: " + ex.GetType().ToString() +
"\r\nMessage: " + ex.Message);
}
Related
People would like to ask you for help with the following situation.
I have a monitor where I check if certain machines are online. To make this process I have a script running on the machine feeding the database with the current time. Already on the monitor, I have an asynchronous check in Infinite loop to pick up the last updated time of the bank and update my Data Grid View. However I'm having some locking problems in this loop, someone could help follow my code
private void timer1_Tick(object sender, EventArgs e)
{
if (timerExec)
{
timerExec = false;
selectStatusRobos();
}
//timer1.Enabled = false;
}
public async void selectStatusRobos()
{
String Configuracao = "server=;user=midas_Client;password=;database=;port=3306";
string query = "SELECT i.Usuario_meta, i.Nome_robo, i.Simbolo, i.Periodo, i.Status_op, i.Operacao, i.Hora_criacao, c.Id, i.Corretora FROM int00 AS i INNER JOIN cliente00 AS c ON i.Usuario_meta = c.Usuario_meta AND i.Corretora = c.Corretora";
MySqlConnection conexao = new MySqlConnection(Configuracao);
try
{
await conexao.OpenAsync();
MySqlCommand COMANDO = new MySqlCommand(query, conexao);
MySqlDataAdapter adapter = new MySqlDataAdapter(COMANDO);
DataTable status = new DataTable();
await adapter.FillAsync(status);
bool flag_find = false;
for (int i = 0; i < dataGridView1.RowCount; i++)
{
flag_find = false;
dataGridView1.Rows[i].Cells["Status"].Value = Properties.Resources.if_exclamation_red_46014;
dataGridView1.Rows[i].Cells["Operacao"].Value = Properties.Resources.if_op_null;
dataGridView1.Rows[i].Cells["Status_op_img"].Value = Properties.Resources.if_op_null;
for (int b = 0; b < status.Rows.Count; b++)
{
if (dataGridView1.Rows[i].Cells["Id"].Value.ToString() == status.Rows[b]["Id"].ToString()
&& dataGridView1.Rows[i].Cells["Usuario_meta"].Value.ToString() == status.Rows[b]["Usuario_meta"].ToString()
&& dataGridView1.Rows[i].Cells["Corretora"].Value.ToString() == status.Rows[b]["Corretora"].ToString()
&& dataGridView1.Rows[i].Cells["Nome_robo"].Value.ToString() == status.Rows[b]["Nome_robo"].ToString()
&& dataGridView1.Rows[i].Cells["Simbolo"].Value.ToString() == status.Rows[b]["Simbolo"].ToString().Substring(0, 3)
&& dataGridView1.Rows[i].Cells["Periodo"].Value.ToString() == status.Rows[b]["Periodo"].ToString())
{
flag_find = true;
dataGridView1.Rows[i].Cells["Status"].Value = Properties.Resources.if_tick_circle_frame_27247;
dataGridView1.Rows[i].Cells["Hora_ultima"].Value = status.Rows[b]["Hora_criacao"].ToString();
if (status.Rows[b]["Operacao"].ToString() == "1") // Compra
{
dataGridView1.Rows[i].Cells["Operacao_img"].Value = Properties.Resources.if_Raise_32535_16;
dataGridView1.Rows[i].Cells["Operacao"].Value = status.Rows[b]["Operacao"].ToString();
}
else if (status.Rows[b]["Operacao"].ToString() == "2") // Venda
{
dataGridView1.Rows[i].Cells["Operacao_img"].Value = Properties.Resources.if_Fall_32468_16;
dataGridView1.Rows[i].Cells["Operacao"].Value = status.Rows[b]["Operacao"].ToString();
}
else
{
dataGridView1.Rows[i].Cells["Operacao_img"].Value = Properties.Resources.if_op_null;
dataGridView1.Rows[i].Cells["Operacao"].Value = status.Rows[b]["Operacao"].ToString();
}
if (status.Rows[b]["Status_op"].ToString() == "2") // Off
{
dataGridView1.Rows[i].Cells["Status_op_img"].Value = Properties.Resources.if_power_off_10214;
dataGridView1.Rows[i].Cells["Status_op"].Value = status.Rows[b]["Status_op"].ToString();
}
else if (status.Rows[b]["Status_op"].ToString() == "1") // On
{
dataGridView1.Rows[i].Cells["Status_op_img"].Value = Properties.Resources.if_power_on_10215;
dataGridView1.Rows[i].Cells["Status_op"].Value = status.Rows[b]["Status_op"].ToString();
}
dataGridView1.Rows[i].Cells["Status"].Value = Properties.Resources.if_tick_circle_frame_27247;
//query = "DELETE FROM `int00` WHERE Usuario_meta = #usuario_meta AND Nome_robo = #nome_robo AND Simbolo = #simbolo AND Periodo = #periodo";
//COMANDO.CommandText = query;
//COMANDO.Parameters.Clear();
//COMANDO.Parameters.Add("#usuario_meta", MySqlDbType.VarChar).Value = status.Rows[b]["Usuario_meta"].ToString();
//COMANDO.Parameters.Add("#nome_robo", MySqlDbType.VarChar).Value = status.Rows[b]["Nome_robo"].ToString();
//COMANDO.Parameters.Add("#simbolo", MySqlDbType.VarChar).Value = status.Rows[b]["Simbolo"].ToString();
//COMANDO.Parameters.Add("#periodo", MySqlDbType.VarChar).Value = status.Rows[b]["Periodo"].ToString();
//COMANDO.ExecuteNonQuery();
//break;
}
if (dataGridView1.Rows[i].Cells["Hora_ultima"].Value != null)
{
DateTime t = Convert.ToDateTime(dataGridView1.Rows[i].Cells["Hora_ultima"].Value.ToString());
// if (dataGridView1.Rows[i].Cells["Hora_ultima"].Value.ToString() != status.Rows[b]["Hora_criacao"].ToString())
if (flag_find)
{
DateTime t1 = DateTime.Now;
DateTime t2 = DateTime.Now.AddSeconds(-30);
System.TimeSpan diff2 = t1.Subtract(t);
if (diff2.TotalSeconds >= 15 && diff2.TotalSeconds <= 45)
{
dataGridView1.Rows[i].Cells["Status"].Value = Properties.Resources.if_58_62715;
}
else if (diff2.TotalSeconds < 15 && diff2.TotalSeconds >= 0)
{
dataGridView1.Rows[i].Cells["Status"].Value = Properties.Resources.if_tick_circle_frame_27247;
}
else
{
dataGridView1.Rows[i].Cells["Status"].Value = Properties.Resources.if_exclamation_red_46014;
}
}
}
}
}
//frm = this.MdiParent as frmPrincipal;
//SendMessage send = new SendMessage(frm.SetLabel);
//send(DateTime.Now.ToString("HH:mm :ss") + " - Dados Atualizados...", null, null);
conexao.Close();
}
catch (MySqlException ex)
{
frm = this.MdiParent as frmPrincipal;
SendMessage send = new SendMessage(frm.SetLabel);
send(DateTime.Now.ToString("HH:mm :ss") + " - Tempo limite excedido na seleção", ex.Message + ex.StackTrace, Properties.Resources.if_Close_Icon_Dark_1398917, 15000);
//MessageBox.Show(ex.Message + ex.StackTrace, "Detalhes Exception");
timerExec = true;
}
catch (TimeoutException ex)
{
frm = this.MdiParent as frmPrincipal;
SendMessage send = new SendMessage(frm.SetLabel);
send(DateTime.Now.ToString("HH:mm :ss") + " - Tempo limite excedido na seleção", ex.Message + ex.StackTrace, Properties.Resources.if_Close_Icon_Dark_1398917, 15000);
timerExec = true;
}
finally
{
frm = this.MdiParent as frmPrincipal;
SendMessage send = new SendMessage(frm.SetLabel);
send(DateTime.Now.ToString("HH:mm :ss") + " - Dados Atualizados...", null, null, 15000);
conexao.Close();
timerExec = true;
}
}
Using .NET 4, wpf c#, I am passing method return values and parameters between two processes.
As I need the connection open and active a all times, I have tried my best to minimize the code that is recurring (within the loop) but unless I put this whole code inside the loop it did not succeed (after the first transfer the connection to server was closed), so as it is here, it does work repeatedly.
I was wondering first is this the way it should be coded, all the process including the new instance, dispose, close... within the loop?
Is the only available datatype for inter-process communication to pass as a string (inefficient)?
public void client()
{
for (int i = 0; i < 2; i++)
{
System.IO.Pipes.NamedPipeClientStream pipeClient =
new System.IO.Pipes.NamedPipeClientStream(".", "testpipe",
System.IO.Pipes.PipeDirection.InOut, System.IO.Pipes.PipeOptions.None);
if (pipeClient.IsConnected != true)
{
pipeClient.Connect(550);
}
System.IO.StreamReader sr = new System.IO.StreamReader(pipeClient);
System.IO.StreamWriter sw = new System.IO.StreamWriter(pipeClient);
string status;
status = sr.ReadLine();
if (status == "Waiting")
{
try
{
sw.WriteLine("param1fileName.cs,33" + i);
sw.Flush();
pipeClient.Close();
}
catch (Exception ex) { throw ex; }
}
}
}
public string server()
{
NamedPipeServerStream pipeServer = null;
do
{
try
{
pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 4);
StreamReader sr = new StreamReader(pipeServer);
StreamWriter sw = new StreamWriter(pipeServer);
System.Threading.Thread.Sleep(100);
pipeServer.WaitForConnection();
string test;
sw.WriteLine("Waiting");
sw.Flush();
pipeServer.WaitForPipeDrain();
test = sr.ReadLine();
if (!string.IsNullOrEmpty(test))
try
{
System.Windows.Application.Current.Dispatcher.Invoke(new Action(() => MbxTw.Show(Convert.ToInt32(test.Split(',')[1]), test.Split(',')[0], "method()", "Warning!! - " + "content")), System.Windows.Threading.DispatcherPriority.Normal);
}
catch (Exception e)
{
}
}
catch (Exception ex) {
throw ex; }
finally
{
pipeServer.WaitForPipeDrain();
if (pipeServer.IsConnected) { pipeServer.Disconnect(); }
}
} while (true);
}
after a thorough research on inter process communication I have changed the approach from using Named pipes to Memory mapped files,
as it is all rounds winner, no need to recreate it and faster
I present the ultimate partitioned-global-app-inter-process communication
any thoughts on the code will be greatly appreciated!
public class MMFinterComT
{
public EventWaitHandle flagCaller1, flagCaller2, flagReciver1, flagReciver2;
private System.IO.MemoryMappedFiles.MemoryMappedFile mmf;
private System.IO.MemoryMappedFiles.MemoryMappedViewAccessor accessor;
public virtual string DepositChlName { get; set; }
public virtual string DepositThrdName { get; set; }
public virtual int DepositSize { get; set; }
private System.Threading.Thread writerThread;
private bool writerThreadRunning;
public int ReadPosition { get; set; }
public List<string> statusSet;
private int writePosition;
public int WritePosition
{
get { return writePosition; }
set
{
if (value != writePosition)
{
this.writePosition = value;
this.accessor.Write(WritePosition + READ_CONFIRM_OFFSET, true);
}
}
}
private List<byte[]> dataToSend;
private const int DATA_AVAILABLE_OFFSET = 0;
private const int READ_CONFIRM_OFFSET = DATA_AVAILABLE_OFFSET + 1;
private const int DATA_LENGTH_OFFSET = READ_CONFIRM_OFFSET + 1;
private const int DATA_OFFSET = DATA_LENGTH_OFFSET + 10;
public IpcMMFinterComSF.MMFinterComTStatus IntercomStatus;
public MMFinterComT(string ctrIpcChannelNameStr, string ctrIpcThreadName, int ctrMMFSize)
{
this.DepositChlName = ctrIpcChannelNameStr;
this.Deposit Size = ctrMMFSize;
this.DepositThrdName = ctrIpcThreadName;
mmf = MemoryMappedFile.CreateOrOpen(DepositChlName, DepositSize);
accessor = mmf.CreateViewAccessor(0, DepositSize, System.IO.MemoryMappedFiles.MemoryMappedFileAccess.ReadWrite);//if (started)
//smLock = new System.Threading.Mutex(true, IpcMutxName, out locked);
ReadPosition = -1;
writePosition = -1;
this.dataToSend = new List<byte[]>();
this.statusSet = new List<string>();
}
public bool reading;
public byte[] ReadData;
public void StartReader()
{
if (this.IntercomStatus != IpcMMFinterComSF.MMFinterComTStatus._Null || ReadPosition < 0 || writePosition < 0)
return;
this.IntercomStatus = IpcMMFinterComSF.MMFinterComTStatus.PreparingReader;
System.Threading.Thread t = new System.Threading.Thread(ReaderThread);
t.IsBackground = true;
t.Start();
}
private void ReaderThread(object stateInfo)
{
// Checks if there is something to read.
this.IntercomStatus = IpcMMFinterComSF.MMFinterComTStatus.TryingToRead;
this.reading = accessor.ReadBoolean(ReadPosition + DATA_AVAILABLE_OFFSET);
if (this.reading)
{
this.IntercomStatus = IpcMMFinterComSF.MMFinterComTStatus.ReadingData;
// Checks how many bytes to read.
int availableBytes = accessor.ReadInt32(ReadPosition + DATA_LENGTH_OFFSET);
this.ReadData = new byte[availableBytes];
// Reads the byte array.
int read = accessor.ReadArray<byte>(ReadPosition + DATA_OFFSET, this.ReadData, 0, availableBytes);
// Sets the flag used to signal that there aren't available data anymore.
accessor.Write(ReadPosition + DATA_AVAILABLE_OFFSET, false);
// Sets the flag used to signal that data has been read.
accessor.Write(ReadPosition + READ_CONFIRM_OFFSET, true);
this.IntercomStatus = IpcMMFinterComSF.MMFinterComTStatus.FinishedReading;
}
else this.IntercomStatus = IpcMMFinterComSF.MMFinterComTStatus._Null;
}
public void Write(byte[] data)
{
if (ReadPosition < 0 || writePosition < 0)
throw new ArgumentException();
this.statusSet.Add("ReadWrite:-> " + ReadPosition + "-" + writePosition);
lock (this.dataToSend)
this.dataToSend.Add(data);
if (!writerThreadRunning)
{
writerThreadRunning = true;
writerThread = new System.Threading.Thread(WriterThread);
writerThread.IsBackground = true;
writerThread.Name = this.DepositThrdName;
writerThread.Start();
}
}
public void WriterThread(object stateInfo)
{
while (dataToSend.Count > 0 && !this.disposed)
{
byte[] data = null;
lock (dataToSend)
{
data = dataToSend[0];
dataToSend.RemoveAt(0);
}
while (!this.accessor.ReadBoolean(WritePosition + READ_CONFIRM_OFFSET))
System.Threading.Thread.Sleep(133);
// Sets length and write data.
this.accessor.Write(writePosition + DATA_LENGTH_OFFSET, data.Length);
this.accessor.WriteArray<byte>(writePosition + DATA_OFFSET, data, 0, data.Length);
// Resets the flag used to signal that data has been read.
this.accessor.Write(writePosition + READ_CONFIRM_OFFSET, false);
// Sets the flag used to signal that there are data avaibla.
this.accessor.Write(writePosition + DATA_AVAILABLE_OFFSET, true);
}
writerThreadRunning = false;
}
public virtual void Close()
{
if (accessor != null)
{
try
{
accessor.Dispose();
accessor = null;
}
catch { }
}
if (this.mmf != null)
{
try
{
mmf.Dispose();
mmf = null;
}
catch { }
}
disposed = true;
GC.SuppressFinalize(this);
}
private bool disposed;
}
and usage
instaciant once !
public static bool StartCurProjInterCom(IpcAccessorSetting curSrv, int DepoSize)
{
if(CurProjMMF ==null)
CurProjMMF = new MMFinterComT(curSrv.Channel.ToString(), curSrv.AccThreadName.ToString(), DepoSize);
CurProjMMF.flagCaller1 = new EventWaitHandle(false, EventResetMode.ManualReset, CurProjMMF.DepositThrdName);
CurProjMMF.flagCaller2 = new EventWaitHandle(false, EventResetMode.ManualReset, CurProjMMF.DepositThrdName);
CurProjMMF.flagReciver1 = new EventWaitHandle(false, EventResetMode.ManualReset, IpcAccessorThreadNameS.DebuggerThrd.ToString());
CurProjMMF.ReadPosition = curSrv.AccessorSectorsSets.DepoSects.Setter.Read;
CurProjMMF.WritePosition = curSrv.AccessorSectorsSets.DepoSects.Setter.Write;
Console.WriteLine("MMFInterComSetter.ReadPosition " + CurProjMMF.ReadPosition);
Console.WriteLine("MMFInterComSetter.WritePosition " + CurProjMMF.WritePosition);
CurProjMMF.StartReader();
return true;
}
use many
public static void StartADebugerInterComCall(IpcCarier SetterDataObj)
{
IpcAccessorSetting curSrv = new IpcAccessorSetting(IpcMMf.IPChannelS.Debugger, IpcAccessorThreadNameS.DebuggerThrdCurProj, 0, 5000);
StartCurProjInterCom(curSrv, 10000);
var dataW = SetterDataObj.IpcCarierToByteArray();//System.Text.Encoding.UTF8.GetBytes(msg);
CurProjMMF.Write(dataW);
CurProjMMF.flagReciver1.Set();
CurProjMMF.flagCaller1.WaitOne();
CurProjMMF.flagCaller1.Reset();
}
I am developing a payroll system in which the attendance should be recorded from finger print machine.I have installed the SDK software, but I don't know how to deploy this in my web application. Also how can we save the finger print in our database so that we could save the attendance details according to finger print
thanks in advance
Fareeda Hussain
We have a project like this one before. You need an sdk (software development kit) to go to your device. Add that to your project references so you can communicate with it. And I believe there is a sample code in the SDK site that you could find in the case of your finger print reader which you could modify.
Anyway here is our sample code for saving fingerprint directly in the database.
private void SaveButton_Click(object sender, EventArgs e)
{
MemoryStream fingerprintData = new MemoryStream();
Template.Serialize(fingerprintData);
fingerprintData.Position = 0;
BinaryReader br = new BinaryReader(fingerprintData);
Byte[] bytes = br.ReadBytes((Int32)fingerprintData.Length);
//Insert the file into database
SqlConnection cn = new SqlConnection("Data Source=10.115.5.3; Initial Catalog=EnrollmentSampledb;Integrated Security=SSPI;");
SqlCommand cmd = new SqlCommand("INSERT INTO tblUser VALUES(#ID_NUMBER, #FIRSTNAME, #LASTNAME, #FINGERPRINT, #DATE_ADDED, #DATE_MODIFIED)", cn);
cmd.Parameters.Add("ID_NUMBER", SqlDbType.NVarChar).Value = tboxIdNum.Text;
cmd.Parameters.Add("FIRSTNAME", SqlDbType.NVarChar).Value = tboxFname.Text;
cmd.Parameters.Add("LASTNAME", SqlDbType.NVarChar).Value = tboxLname.Text;
cmd.Parameters.Add("FINGERPRINT", SqlDbType.Image).Value = bytes;
cmd.Parameters.Add("DATE_ADDED", SqlDbType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add("DATE_MODIFIED", SqlDbType.DateTime).Value = DateTime.Now;
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
tboxIdNum.Text = "";
tboxFname.Text = "";
tboxLname.Text = "";
}
see also my similar question here for saving fingerprint directly in the database.
region Funsional FingerPrint
protected void ReaderFPMachine()
{
_readerCollection = ReaderCollection.GetReaders();
foreach (Reader Reader in _readerCollection)
{
_fPMachineID = Reader.Description.SerialNumber;
break;
}
this.CheckFingerPrint();
}
protected void CheckFingerPrint()
{
try
{
_finger = null;
_reader = _readerCollection[0];
if (!OpenReader())
{
//this.Close();
}
if (!StartCaptureAsync(this.OnCaptured))
{
//this.Close();
}
}
catch (Exception ex)
{
}
}
private void OnCaptured(CaptureResult captureResult)
{
try
{
_finger = null;
// Check capture quality and throw an error if bad.
if (!CheckCaptureResult(captureResult)) return;
//SendMessage(Action.SendMessage, "A finger was captured.");
DataResult<Fmd> resultConversion = FeatureExtraction.CreateFmdFromFid(captureResult.Data, Constants.Formats.Fmd.ANSI);
if (resultConversion.ResultCode != Constants.ResultCode.DP_SUCCESS)
{
_reset = true;
throw new Exception(resultConversion.ResultCode.ToString());
}
_finger = resultConversion.Data;
_fingerPrintID = Fmd.SerializeXml(_finger);
//MsVisitorHd _msVisitorHd = this._vMSBL.GetSingleMsVisitorHdByFingerPrintID(_fingerXML);
//List<MsVisitorHd> _listMsVisitorHd = this._vMSBL.GetListMsVisitorHd();
bool _exist = false;
//foreach (var _item in _listMsVisitorHd)
//{
// Fmd _fmd = Fmd.DeserializeXml(_fingerPrintID);
// Fmd _fmd2 = Fmd.DeserializeXml(_item.FingerPrintID);
// CompareResult compareResult = Comparison.Compare(_fmd, 0, _fmd2, 0);
// if (compareResult.ResultCode != Constants.ResultCode.DP_SUCCESS)
// {
// _reset = true;
// throw new Exception(compareResult.ResultCode.ToString());
// }
// else
// {
// if (compareResult.Score < (PROBABILITY_ONE / 100000))
// {
// //_visitorExist = new MsVisitorHd();
// //_visitorExist = _item;
// _exist = true;
// break;
// }
// else
// {
// }
// }
//}
if (!CheckCaptureResult(captureResult)) return;
// Create bitmap
foreach (Fid.Fiv fiv in captureResult.Data.Views)
{
this.FingerPictureBox.BackgroundImage = CreateBitmap(fiv.RawImage, fiv.Width, fiv.Height);
}
if (_exist)
{
_fgMember = "Y";
//MessageBox.Show("Sidik jadi terdaftar sebagai " + _visitorExist.VisitorName);
}
else
{
_fgMember = "N";
}
//SendMessage(Action.SendMessage, secondFinger.Bytes.ToString() + "Comparison resulted in a dissimilarity score of " + compareResult.Score.ToString() + (compareResult.Score < (PROBABILITY_ONE / 100000) ? " (fingerprints matched)" : " (fingerprints did not match)"));
//SendMessage(Action.SendMessage, "Place a finger on the reader.");
// count = 0;
//}
}
catch (Exception ex)
{
// Send error message, then close form
//SendMessage(Action.SendMessage, "Error: " + ex.Message);
}
}
public bool OpenReader()
{
_reset = false;
Constants.ResultCode result = Constants.ResultCode.DP_DEVICE_FAILURE;
// Open reader
result = _reader.Open(Constants.CapturePriority.DP_PRIORITY_COOPERATIVE);
if (result != Constants.ResultCode.DP_SUCCESS)
{
MessageBox.Show("Error: " + result);
_reset = true;
return false;
}
return _reset;
}
public void GetStatus()
{
Constants.ResultCode result = _reader.GetStatus();
if ((result != Constants.ResultCode.DP_SUCCESS))
{
_reset = true;
throw new Exception("" + result);
}
if ((_reader.Status.Status == Constants.ReaderStatuses.DP_STATUS_BUSY))
{
Thread.Sleep(50);
}
else if ((_reader.Status.Status == Constants.ReaderStatuses.DP_STATUS_NEED_CALIBRATION))
{
_reader.Calibrate();
}
else if ((_reader.Status.Status != Constants.ReaderStatuses.DP_STATUS_READY))
{
throw new Exception("Reader Status - " + _reader.Status.Status);
}
}
public bool CheckCaptureResult(CaptureResult captureResult)
{
if (captureResult.Data == null)
{
if (captureResult.ResultCode != Constants.ResultCode.DP_SUCCESS)
{
_reset = true;
throw new Exception(captureResult.ResultCode.ToString());
}
// Send message if quality shows fake finger
if ((captureResult.Quality != Constants.CaptureQuality.DP_QUALITY_CANCELED))
{
throw new Exception("Quality - " + captureResult.Quality);
}
return false;
}
return true;
}
public bool CaptureFingerAsync()
{
try
{
GetStatus();
Constants.ResultCode captureResult = _reader.CaptureAsync(Constants.Formats.Fid.ANSI, Constants.CaptureProcessing.DP_IMG_PROC_DEFAULT, _reader.Capabilities.Resolutions[0]);
if (captureResult != Constants.ResultCode.DP_SUCCESS)
{
_reset = true;
throw new Exception("" + captureResult);
}
return true;
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
return false;
}
}
public Bitmap CreateBitmap(byte[] bytes, int width, int height)
{
byte[] rgbBytes = new byte[bytes.Length * 3];
for (int i = 0; i <= bytes.Length - 1; i++)
{
rgbBytes[(i * 3)] = bytes[i];
rgbBytes[(i * 3) + 1] = bytes[i];
rgbBytes[(i * 3) + 2] = bytes[i];
}
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
for (int i = 0; i <= bmp.Height - 1; i++)
{
IntPtr p = new IntPtr(data.Scan0.ToInt64() + data.Stride * i);
System.Runtime.InteropServices.Marshal.Copy(rgbBytes, i * bmp.Width * 3, p, bmp.Width * 3);
}
bmp.UnlockBits(data);
return bmp;
}
public bool StartCaptureAsync(Reader.CaptureCallback OnCaptured)
{
// Activate capture handler
_reader.On_Captured += new Reader.CaptureCallback(OnCaptured);
// Call capture
if (!CaptureFingerAsync())
{
return false;
}
return true;
}
#endregion
Below code is used to move the data from local system to external hard drives. Client's requirement is to use threading for the same so as to speed up the copy of pages / minute.
I am facing one issue. I used continue statement under while loop which is not acceptable under thread. Can someone please suggest alternative of the same.
Thanks.
private void PromoteMain(TextWriter streamWriter)
{
string driveLetterString;
driveLetterString = GetExternalDrive();
if (!string.IsNullOrEmpty(driveLetterString))
{
DataSet dataSet;
DateTime startSnooze;
DataRow row;
string imageIdString;
string reelIdString;
string destImagePathString;
string[] strArrays;
int i;
string fileName;
string[] strArrays3;
string[] strArrays4;
bool flag;
string[] strArrays5;
bool flag1;
string[] strArrays6;
bool flag2;
string[] files;
TimeSpan timeSpan1;
IEnumerator iEnumerator1;
string[] stringArray1;
IDisposable iDisposable1;
dataSet = this.GetImagesFromDatabase();
if (((dataSet != null) && (dataSet.Tables.Count != 0)) && (dataSet.Tables[0].Rows.Count != 0))
{
iEnumerator1 = dataSet.Tables[0].Rows.GetEnumerator();
try
{
#region goto L_05A9
//goto L_05A9;
while (iEnumerator1.MoveNext())
{
driveLetterString = GetExternalDrive();
new Thread(() =>
{
if (!string.IsNullOrEmpty(driveLetterString))
{
row = ((DataRow)iEnumerator1.Current);
imageIdString = row["imageid"].ToString();
reelIdString = row["reelid"].ToString();
destImagePathString = row["destimagepath"].ToString();
if (!Directory.Exists(destImagePathString))
{
if (this.stringBuilderFail.Length > 0)
{
StringBuilder stringBuilder7 = this.stringBuilderFail.Append(",");
}
StringBuilder stringBuilder8 = this.stringBuilderFail.Append(imageIdString);
this._lblFailed.Text = Convert.ToString(((int)(Convert.ToInt32(this._lblFailed.Text) + 1)));
if (this.stringBuilderFail.Length > 7000)
{
this.UpdateImagesInDatabase(this.stringBuilderFail.ToString(), "5");
StringBuilder stringBuilder9 = this.stringBuilderFail.Remove(0, this.stringBuilderFail.Length);
}
this.RefreshFormView();
continue;
}
if (!Directory.Exists((driveLetterString + "newspaper\\" + reelIdString + "\\")))
{
DirectoryInfo directoryInfo1 = Directory.CreateDirectory((driveLetterString + "newspaper\\" + reelIdString + "\\"));
}
strArrays = new string[] { ".pdf", ".html", "_clean.html", "_lx.jpg" };
for (i = 0; (i < strArrays.Length); i++)
{
fileName = strArrays[i];
try
{
if (i != 2)
{
strArrays3 = new string[] { driveLetterString, "newspaper\\", reelIdString, "\\", imageIdString, fileName };
File.Copy((destImagePathString + imageIdString + fileName), string.Concat(strArrays3));
}
}
catch
{
}
}
strArrays4 = new string[] { driveLetterString, "newspaper\\", reelIdString, "\\", imageIdString, ".pdf" };
flag = File.Exists(string.Concat(strArrays4));
strArrays5 = new string[] { driveLetterString, "newspaper\\", reelIdString, "\\", imageIdString, "_lx.jpg" };
flag1 = File.Exists(string.Concat(strArrays5));
strArrays6 = new string[] { driveLetterString, "newspaper\\", reelIdString, "\\", imageIdString, ".html" };
flag2 = File.Exists(string.Concat(strArrays6));
if ((flag && flag1) && flag2)
{
streamWriter.WriteLine(imageIdString);
if (this.stringBuilderSuccess.Length > 0)
{
StringBuilder stringBuilder3 = this.stringBuilderSuccess.Append(",");
}
StringBuilder stringBuilder4 = this.stringBuilderSuccess.Append(imageIdString);
this._lblPromoted.Text = Convert.ToString(((int)(Convert.ToInt32(this._lblPromoted.Text) + 1)));
#region goto L_0453
L_0453();
continue;
#endregion
}
files = Directory.GetFiles((driveLetterString + "newspaper\\" + reelIdString + "\\"), (imageIdString + "*.*"));
stringArray1 = files;
foreach (string str6 in stringArray1)
{
try
{
File.Delete(str6);
}
catch
{
}
}
if (this.stringBuilderFail.Length > 0)
{
StringBuilder stringBuilder1 = this.stringBuilderFail.Append(",");
}
StringBuilder stringBuilder2 = this.stringBuilderFail.Append(imageIdString);
this._lblFailed.Text = Convert.ToString(((int)(Convert.ToInt32(this._lblFailed.Text) + 1)));
#region goto L_0453
L_0453();
continue;
#endregion
}
else
{
break;
};
}).Start();
}
#endregion
}
finally
{
iDisposable1 = (iEnumerator1 as IDisposable);
if (iDisposable1 != null)
{
iDisposable1.Dispose();
}
}
if (this.stringBuilderSuccess.Length > 0)
{
this.UpdateImagesInDatabase(this.stringBuilderSuccess.ToString(), "3");
StringBuilder stringBuilder10 = this.stringBuilderSuccess.Remove(0, this.stringBuilderSuccess.Length);
}
if (this.stringBuilderFail.Length > 0)
{
this.UpdateImagesInDatabase(this.stringBuilderFail.ToString(), "5");
StringBuilder stringBuilder11 = this.stringBuilderFail.Remove(0, this.stringBuilderFail.Length);
}
this.RefreshFormView();
#region goto L_0671
PromoteMain(streamWriter);
#endregion
}
else
{
startSnooze = DateTime.Now;
timeSpan1 = DateTime.Now.Subtract(startSnooze);
while (timeSpan1.TotalSeconds < 300D)
{
timeSpan1 = DateTime.Now.Subtract(startSnooze);
Thread.Sleep(125);
Application.DoEvents();
}
PromoteMain(streamWriter);
}
}
//else
//{
// MessageBox.Show("There is no space in selected drives");
// //there is no space in any external drive
//}
}
private void L_0453()
{
if (this.stringBuilderSuccess.Length > 7000)
{
this.UpdateImagesInDatabase(this.stringBuilderSuccess.ToString(), "3");
StringBuilder stringBuilder5 = this.stringBuilderSuccess.Remove(0, this.stringBuilderSuccess.Length);
}
if (this.stringBuilderFail.Length > 7000)
{
this.UpdateImagesInDatabase(this.stringBuilderFail.ToString(), "5");
StringBuilder stringBuilder6 = this.stringBuilderFail.Remove(0, this.stringBuilderFail.Length);
}
this.RefreshFormView();
}
Replace the continue statement with a return. This will complete the execution of the thread. Now I don't know how this continue statement ended up there but you can't actually continue since the operations are running in parallel. You should also extract this line
row = ((DataRow)iEnumerator1.Current);
or you risk the enumerator to change from another thread before it executes. You may also want to try Parallel.Foreach to reduce possible errors and get more effective execution. Even better would be to use async methods with async IO (as opposed to methods that use threads) and use Task.WaitAll to wait for them to complete.
I'm newbie in SQLITE and I'm currently using System.Data.SQLite.dll version 1.0.89.0 in a C# project.
My database contains a simple table 'files' with following columns:
[id] VARCHAR(50) NOT NULL
[chunk] INTEGER NOT NULL
[content] BLOB NOT NULL
[size] INTEGER NOT NULL
[date_ins] DATETIME NOT NULL
PRIMARY KEY(id,chunk)
I created a class (OfflineStorage) to add and retrieve files in this table as BLOBS.
Save method works ok, but Load generate an InvalidCastException on GetStream extended method.
public class OfflineStorage
{
private static string l_strConnectionTemplate = "Data Source={0};Version=3;Password=\"{1}\";";
private string l_strConnection;
private int SQLITE_MAX_BLOB_LENGTH;
private string l_strCreateTable = #"CREATE TABLE IF NOT EXISTS [files]" +
"( " +
" [id] VARCHAR(50) NOT NULL, " +
" [chunk] INTEGER NOT NULL, " +
" [content] BLOB NOT NULL, " +
" [size] INTEGER NOT NULL, " +
" [date_ins] DATETIME NOT NULL, " +
" PRIMARY KEY(id,chunk) " +
")";
private string l_strSelectQuery = #"SELECT chunk, content, size FROM files WHERE id = #id ORDER BY chunk";
private string l_strUpdateQuery = #"UPDATE files SET content = content || #new_content, size = size + #size WHERE id = #id AND chunk = #chunk";
private string l_strInsertQuery = #"INSERT INTO files(id, chunk, content, size, date_ins) VALUES(#id, #chunk, #new_content, #size, DATETIME('now'))";
public OfflineStorage(string strFilename, string strPassword = "")
{
SQLiteConnection l_objConnection = null;
if (!File.Exists(strFilename))
{
l_strConnection = string.Format(l_strConnectionTemplate, strFilename, "");
SQLiteConnection.CreateFile(strFilename);
l_objConnection = new SQLiteConnection(l_strConnection);
l_objConnection.SetPassword(strPassword);
l_objConnection.Close();
}
l_strConnection = string.Format(l_strConnectionTemplate, strFilename, strPassword);
l_objConnection = getConnection();
using (SQLiteCommand l_objCommand = new SQLiteCommand(l_strCreateTable, l_objConnection))
{
l_objCommand.ExecuteNonQuery();
}
SQLITE_MAX_BLOB_LENGTH = 1000000;
CloseConnection(l_objConnection);
}
private SQLiteConnection getConnection()
{
SQLiteConnection l_objConnection = null;
try
{
l_objConnection = new SQLiteConnection(l_strConnection);
l_objConnection.Open();
return l_objConnection;
}
catch (Exception ex)
{
CloseConnection(l_objConnection);
throw new OfflineStorageException("Local Service open db error.", ex);
}
}
private void CloseConnection(SQLiteConnection objConnection)
{
if (objConnection != null)
{
objConnection.Close();
objConnection = null;
}
}
public long Load(string strID, Stream objStream)
{
if (!objStream.CanWrite)
throw new NotSupportedException("Stream not writable.");
SQLiteConnection l_objConnection = getConnection();
// Columns Identifier (name of file)
SQLiteParameter l_objID = new SQLiteParameter("#id", DbType.String);
l_objID.Value = strID;
SQLiteCommand l_objCommand = new SQLiteCommand(l_strSelectQuery, l_objConnection);
l_objCommand.Parameters.Add(l_objID);
// Load File Records
SQLiteDataReader l_objReader;
try
{
l_objReader = l_objCommand.ExecuteReader();
}
catch (Exception ex)
{
CloseConnection(l_objConnection);
throw new OfflineStorageException("SQLite exception.", ex);
}
long l_lFileLength = 0; // Complete file length
int l_iDBChunk = -1; // Current chunk on database
int l_iChunk = 0; // Current 'sub chunk'
long l_lChunkLength = -1; // Current 'sub chunk' length
try
{
// For each record of current file selected by identifier
while (l_objReader.Read())
{
l_iDBChunk = l_objReader.GetInt32(0); // Chunk ID
l_lChunkLength = l_objReader.GetInt64(2); // Chunk size
Trace.Assert(l_iChunk == l_iDBChunk); // Compare expected Chunck with Database ID Chunk
l_lFileLength += l_objReader.GetStream(objStream, 1, l_lChunkLength); // Load chunk
l_iChunk++;
}
}
catch (Exception ex)
{
string l_strMessage = string.Format("SQLite exception on file {0}, DB chunk {1}: \n{2}", strID, l_iDBChunk, ex.Message);
throw new OfflineStorageException(l_strMessage, ex);
}
finally
{
l_objReader.Close();
l_objCommand.Dispose();
CloseConnection(l_objConnection);
}
if (l_iChunk < 1)
{
string l_strMessage = string.Format("File {0} not readed on db.", strID);
throw new OfflineStorageException(l_strMessage);
}
return l_lFileLength;
}
public void Save(string strID, Stream objStream, bool bOverwrite = false)
{
const int CHUNK_SIZE = 8 * 1024;
if (!objStream.CanRead)
throw new NotSupportedException("Stream not readable.");
long l_lOldPosition = objStream.Position;
SQLiteConnection l_objConnection = getConnection();
byte[] lar_byBuffer = new byte[CHUNK_SIZE];
SQLiteParameter l_objID = new SQLiteParameter("#id", DbType.String);
l_objID.Value = strID;
SQLiteParameter l_objContent = new SQLiteParameter("#new_content", DbType.Binary);
l_objContent.Value = lar_byBuffer;
SQLiteParameter l_objChunk = new SQLiteParameter("#chunk", DbType.Int32);
SQLiteParameter l_objSize = new SQLiteParameter("#size", DbType.Int32);
SQLiteCommand l_objCommand = new SQLiteCommand(l_strInsertQuery, l_objConnection);
l_objCommand.Parameters.Add(l_objID);
l_objCommand.Parameters.Add(l_objContent);
l_objCommand.Parameters.Add(l_objChunk);
l_objCommand.Parameters.Add(l_objSize);
int l_iReturn, l_lBytesRead;
int l_iChunk = 0; // Current 'sub chunk'
int l_iDBChunk = 0; // Current chunk on database
long l_lDBChunkLength = 0; // Current length of chunk
l_objChunk.Value = l_iDBChunk;
//Transaction
using (SQLiteTransaction l_objTransaction = l_objConnection.BeginTransaction())
{
// Read File from stream
while ((l_lBytesRead = objStream.Read(lar_byBuffer, 0, lar_byBuffer.Length)) > 0)
{
// Check for next Chunk
if ((l_lDBChunkLength + l_lBytesRead) >= SQLITE_MAX_BLOB_LENGTH)
{
l_objCommand.CommandText = l_strInsertQuery;
l_iChunk = 0; // reset 'sub chunk' counter
l_lDBChunkLength = 0; // reset chunk size
l_iDBChunk++; // increase chunk ID
l_objChunk.Value = l_iDBChunk;
}
l_lDBChunkLength += l_lBytesRead; // Increase length of chunk
l_objContent.Size = l_lBytesRead; // Length of Content field
l_objSize.Value = l_lBytesRead; // Chunk lenght (write on 'size' column)
#region WRITE
try
{
l_iReturn = l_objCommand.ExecuteNonQuery();
if (l_iChunk == 0)
{
l_objCommand.CommandText = l_strUpdateQuery;
}
}
catch (Exception ex)
{
l_objTransaction.Rollback();
CloseConnection(l_objConnection);
string l_strMessage = string.Format("SQLite exception on file {0}, DB chunk {1}, chunk {2}: \n{3}", strID, l_iDBChunk, l_iChunk, ex.Message);
throw new OfflineStorageException(l_strMessage, ex);
}
if (l_iReturn != 1)
{
l_objTransaction.Rollback();
CloseConnection(l_objConnection);
string l_strMessage = string.Format("DB chunk {1}, chunk {2} of file {0} not inserted on db.", strID, l_iDBChunk, l_iChunk);
throw new OfflineStorageException(l_strMessage);
}
#endregion WRITE
l_iChunk++;
}
l_objTransaction.Commit();
}
l_objCommand.Dispose();
CloseConnection(l_objConnection);
objStream.Position = l_lOldPosition;
}
}
DB Data Reader Extended class:
public static class DbDataReaderExtension
{
public static long GetStream(this DbDataReader objReader, System.IO.Stream objStream, int iIndex = 0, long lFileLength = -1)
{
const int CHUNK_SIZE = 7 * 1024;
byte[] lar_byBuffer = new byte[CHUNK_SIZE]; // Buffer
long l_lBytesRead; // Bytes readed from SQLite database column
long l_lFieldOffset = 0; // Field offset on database column
long l_lBytesRemainig = lFileLength;
while ((l_lBytesRead = objReader.GetBytes(iIndex, l_lFieldOffset, lar_byBuffer, 0, lar_byBuffer.Length)) > 0)
{
l_lFieldOffset += l_lBytesRead; // prepare next offset
if (l_lBytesRemainig > 0) // check if a FileLength was set
{
l_lBytesRemainig -= l_lBytesRead; // remove readed bytes
if (l_lBytesRemainig < 0) // Cut last bytes not valid if file is bigger than column size
l_lBytesRead += l_lBytesRemainig;
}
// write only valid bytes
objStream.Write(lar_byBuffer, 0, (int)l_lBytesRead);
}
return lFileLength < 0 ? l_lFieldOffset : lFileLength;
}
}
I found this exception is generated because ReadBytes method (SQLiteDataReader) call VerifyType
private TypeAffinity VerifyType(int i, DbType typ)
{
CheckClosed();
CheckValidRow();
TypeAffinity affinity = GetSQLiteType(i).Affinity;
switch (affinity)
{
...
case TypeAffinity.Text:
if (typ == DbType.SByte) return affinity;
if (typ == DbType.String) return affinity;
if (typ == DbType.SByte) return affinity;
if (typ == DbType.Guid) return affinity;
if (typ == DbType.DateTime) return affinity;
if (typ == DbType.Decimal) return affinity;
break;
case TypeAffinity.Blob:
...
}
throw new InvalidCastException();
}
In this function isn't expected that typ is equal to DbType.Binary and affinity is equal to TypeAffinity.Text.
Can anyone help me to understand this problem?
Thank you
ok, here's how i have added and retrieved blobs.
i suppose it all depends on whether the byte[] is a manageable size. This worked for small objects being serialized to the database.
use GetDataTable to get the data and then on the row in question extract the byte array with the following:
public byte[] getByteArray(DataRow row, int offset)
{
object blob = row[offset];
if (blob == null) return null;
byte[] arData = (byte[])blob;
return arData;
}
this is how i add them:
private System.Object syncLock = new System.Object();
public int ExecuteNonQueryWithBlob(string sql, string blobFieldName, byte[] blob)
{
lock (syncLock)
{
try
{
using (var c = new SQLiteConnection(dbConnection))
{
using (var cmd = new SQLiteCommand(sql, c))
{
cmd.Connection.Open();
cmd.Parameters.AddWithValue("#" + blobFieldName, blob);
return cmd.ExecuteNonQuery();
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return 0;
}
}
}
public DataTable GetDataTable(string sql)
{
lock (syncLock)
{
try
{
DataTable dt = new DataTable();
using (var c = new SQLiteConnection(dbConnection))
{
c.Open();
using (SQLiteCommand cmd = new SQLiteCommand(sql, c))
{
using (SQLiteDataReader rdr = cmd.ExecuteReader())
{
dt.Load(rdr);
return dt;
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
}