|
Hello,
Thanks for the reply. Let me address your questions in order:
1. The reason that I say the size for MISSING_TRANS is 24 bytes is that there are 6 occurences of the array and SizeOf sees MISSING_TRANS as a 4 byte reference instead of an 8 byte structure. What I was hoping with the MarshalAs attribute was to get the data marshalled so that SizeOf would see MISSING_TRANS as 48 bytes, what it should be.
2. Yes MISSING_TRANS is declared as a class but I believe it is really being used as a structure thus allowing me to use the [StructLayout(LayoutKind.Sequential, Pack = 1)] attribute.
I see your point about keeping the structure as simple as possible. I haven't used P/Invoke before and will have to look into it. I was just wondering if anyone had successfully used MarshalAs on an array of structures. Again thanks for the reply.
|
|
|
|
|
Hi,
some comments:
0.
I now see you were referring to the MISSING_TRANS[] array inside REGISTER_TOTALS, not MISSING_TRANS itself.
1.
as I've told you before your MISSING_TRANS was defined as a class, not a struct; that is where you went wrong. Make it a struct, and its data will sit right in the array of fixed size inside REGISTER_TOTALS. As long as MISSING_TRANS is a class all REGISTER_TOTALS can do is hold pointers to it's instances.
2.
I'm not sure whether REGISTER_TOTALS will Marshal fine as that is a class too; consider making it a struct!
3.
FYI: references/pointers would take 4 bytes each on Win32 and 8 on Win64. IntPtr takes care of that, however a lot of P/Invoke examples are plain wrong in this respect.
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
|
|
|
|
|
That did the trick. I forgot that structures are passed by value and classes by reference. REGISTER_TOTALS does marshal okay. Thanks for all of your help.
|
|
|
|
|
you're welcome.
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
|
|
|
|
|
Hi
Im building a windows application that needs to interact with a database.
For this I created a database worker thread.
I send sql queries to the "database worker thread" and when ready it will put them in a Qeueue that I read from the "Main" thread.
But when I try to for example put the result in a listview I get a "Cross thread Exception".
Why?
If you look at the image below you will understand what Im trying to do.
http://i25.tinypic.com/2saie05.png[^]
Very much thankful for any ideas!
|
|
|
|
|
seems like OnNewResult is running on the thread that caused it to happen, I would guess your BackgroundWorker; hence it can't touch any GUI Controls.
You need to:
- either use Control.InvokeRequired/Control.Invoke
- or let BGW.ReportProgress do the job (it Invokes the GUI thread for you)
While your picture is a work of art, "putting classes inside threads" as it suggests, is misleading;
code does not sit inside a thread, code sits in memory, and one or more threads can/could execute it.
Here enqueueWithEvent runs on something other than the main thread.
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
|
|
|
|
|
@Luc Pattyn
yeah, isnt the picture great
Unfortuntly I dont have the code avaiible otherwise I would have posted it.
Anyway, as I see it the two Queues are in thread "neutral" lands. So if "Main" thread assigns a Eventlistener to the resultQueue it should be the "Main" thread that gets the event.
bases on the error it must be the Database worker thread that somehow manages to execute the OnnewResult() function!?
|
|
|
|
|
raising an event is just like calling a method, it happens on the thread that executes the code; here the thread that calls enqueueWithEvent, and that is clearly the same one doing the DoWork() stuff, which is bound to be a threadpool thread, as BGWs run on them, not on the main thread.
You can hope and dream all you want, but you have to make it happen. As I said, use either Controle.Invoke or BGW.ReportProgress; for a general-purpose queue, it has to be Control.Invoke
There is one alternative, rather than telling the queue about your Controls, give the queue an event, and let your Form wire a delegate to it, where the delegate itself does the necessary Invoke stuff (after all, to be a proper queue the queue does not have to know about a GUI, all it needs is a way to signal its customers, and that is events+delegates).
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
|
|
|
|
|
First off, Im really greatful for your answers!
The thing is that Im not really understanding my own code, im quite a noob when it comes to threading. Thats why i "push" you to explain my design errors.
I will have a look at the "delegates" thing and have another go at this.
Thanks again!
|
|
|
|
|
David8001C wrote: Im not really understanding my own code
That is unacceptable. It is hard enough when you think you do understand your code and it sometimes doesn't do what you expect.
Here is some great advice[^] for you
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
|
|
|
|
|
Hi David,
I just finished a little article on the cross-thread problem, so here[^] is a read for you. It does assume you are familiar with delegates though. I might create an article on delegates and events at some other time.
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get.
Show formatted code inside PRE tags, and give clear symptoms when describing a problem.
|
|
|
|
|
Read the documentation.
You'll need to check InvokeRequired and Invoke as needed.
|
|
|
|
|
Hi
Is there any way to copy assmeblies that registered in GAC to local drive ?
thanks
|
|
|
|
|
Yes through the command prompt.
|
|
|
|
|
yes, command prompt or free commander (like windows explorer)
|
|
|
|
|
hdv212 wrote: Is there any way to copy assmeblies that registered in GAC to local drive ?
Lets you want to copy System.Data.dll from GAC [ Just for Example ]
Open Command Prompt.
Move to Directory
C:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089>
Use DIR
07/04/2009 04:12 PM <DIR> .
07/04/2009 04:12 PM <DIR> ..
07/04/2009 04:12 PM x,xxx,xxx System.Data.dll
1 File(s) x,xxx,xxx bytes
2 Dir(s) xx,xxx,xxx,xxx bytes free
Now use Copy command to copy the System.Data.Dll
cheers,
Abhijit
CodeProject MVP
Web Site:abhijitjana.net
When you ask a question, remember to click "Good Answer", If the Answer is helps you.
|
|
|
|
|
Hello everyone,
2 days ago i bought a relays card wich is controlled by rs232 ComPort.
It works with the suplied software, that's written in visual basic.
But i code in visual c#, so i downloaded visual basic but i have som problem understanding how to convert sertan things from visual basic to c#.
i will post some code and hope someone could help me out, the problem is in a byte buffer, wich wil sent the commands to my serial port.
Send_buffer(0) = 2 ' Get Ports
Send_buffer(1) = 0 ' Broadcast
Send_buffer(2) = 0
Send_buffer(3) = Send_buffer(0) Xor Send_buffer(1) Xor Send_buffer(2)
SerialPort1.Write(Send_buffer, 0, 4)
i know a little bit what is happening here, but i dont know how to use it in c# thanks so far;)
|
|
|
|
|
Okay, the first four lines are arrays. That mean that you can refer to them like you do in VB, but the brackets need to be square [] instead of curly (). XOR is a logical operator, the equivalent in C# is the ^ symbol. The method call is the same. Don't forget the semicolons at the end of every statement
As to what happens on a high level, you simply fill a small array with numbers and send it over a serial port
Between the idea
And the reality
Between the motion
And the act
Falls the Shadow
|
|
|
|
|
Computafreak wrote: instead of curly ().
Parentheses () aren't curly, braces {} are.
|
|
|
|
|
Ah, my terminology is a bit off. To me, () are curly, [] are square, {} are squiggly. Unsurprisingly, I feel rather silly when I talk about programming syntax
Between the idea
And the reality
Between the motion
And the act
Falls the Shadow
|
|
|
|
|
i now have this:
ArrayList al = new ArrayList();
al[1] = 8;
al[2] = 1;
al[3] = 3;
al[4] = 8 ^ 1 ^ 4;
serialPort1.Open();
serialPort1.Write(al, 0, 4);
serialPort1.Close();
but it returns this error:
Error 2 Argument '1': cannot convert from 'System.Collections.ArrayList' to 'byte[]' C:\Users\Clean Totaal\AppData\Local\Temporary Projects\WindowsFormsApplication1\Form1.cs 31 31 WindowsFormsApplication1
What is going wrong?
|
|
|
|
|
Using your example above try (remember arrays are zero based in c#, not 1):
byte[] ab = new byte[4];
ab[0] = 8;
ab[1] = 1;
ab[2] = 3;
ab[3] = ab[0] ^ ab[1] ^ ab[2];
serialPort1.Open();
serialPort1.Write(ab, 0, 4);
serialPort1.Close();
No trees were harmed in the sending of this message; however, a significant number of electrons were slightly inconvenienced.
This message is made of fully recyclable Zeros and Ones
|
|
|
|
|
Thank YOU its working!!
|
|
|
|
|
byte[] al = new byte [ 4 ] ;
|
|
|
|
|
Here is my Code
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Data.Odbc;
using My;
using System.Data;
namespace FirstCitizensBank_DropOffReport
{
class Program : MyGeneral
{
public static string dataBasePath;
public static string dbname;
public static string strconn;
static void Main(string[] args)
{
StartUp("", "", true);
dataBasePath = ConfigPath + "Empathic\\FirstCit\\";
dbname = "Bank";
strconn = "";
try
{
string repname = dataBasePath + "Reports\\Dropoff" + myDate.ToString("yyyyMMdd") + ".xls";
DateTime enddate = myDate.AddDays(-myDate.Day);
DateTime startdate = enddate.AddDays(1).AddMonths(-1);
MyWriteExcel exl = new MyWriteExcel(repname, dataBasePath + "Reports\\Templates\\DropoffTemp.xls");
enddate = startdate.AddDays(-1);
dbname = "Bank";
dbname = dbname + myDate.AddMonths(-1).ToString("yyMM");
WriteMonth(ref exl, startdate, enddate, "C");
enddate = startdate.AddDays(-1);
startdate = startdate.AddMonths(-2);
dbname = "Bank";
dbname = dbname + myDate.AddMonths(-2).ToString("yyMM");
WriteMonth(ref exl, startdate, enddate, "D");
exl.Save();
exl.Close();
MyEmail email = new MyEmail("", "First Citizens Bank Dropoff Report", "Please see attached report");
email.AddAttachment(repname);
email.AddBCC(CommonEmail);
email.sendEmail();
endProgram();
}
catch (Exception e)
{
WriteToLog("@Failed: " + e.ToString());
HelpPage(e.ToString(), "Failed");
}
}
public static void WriteMonth(ref MyWriteExcel exl, DateTime startdate, DateTime enddate, string column)
{
string sql = "select count(*) as total, sum(iif(mid(CALLSTATUS, 1, 2) >= '06', 1, 0)) as entered, sum(iif(DONE is not null, 1, 0)) as completed"
+ " from " + dbname + " where startdate >= " + startdate.ToString("yyyyMMdd") + " and startdate <= " + enddate.AddMonths(+1).ToString("yyyyMMdd")
+ " and stopdate is not null";
OdbcConnection conn = new OdbcConnection(strconn);
conn.Open();
OdbcCommand cmd = new OdbcCommand(sql, conn);
OdbcDataReader dr = cmd.ExecuteReader();
dr.Read();
int total;
int entered;
int completed;
int abandoned;
if (!(int.TryParse(dr["total"].ToString(), out total) && int.TryParse(dr["entered"].ToString(), out entered) && int.TryParse(dr["completed"].ToString(), out completed)))
{
Exception myex = new Exception("Failed to convert one of the counts to an integer");
throw myex;
}
dr.Close();
dr.Dispose();
abandoned = entered - completed;
sql = "select avg(duration) as avgdur from " + dbname + myDate.AddMonths(-1).ToString("yyMM") + " where startdate >= " + startdate.ToString("yyyyMMdd") + " and startdate <= " + enddate.AddMonths(+1).ToString("yyyyMMdd")
+ " and stopdate is not null and DONE is not null";
cmd.CommandText = sql;
dr = cmd.ExecuteReader();
dr.Read();
double avgcompleted;
if (!double.TryParse(dr["avgdur"].ToString(), out avgcompleted))
{
Exception myex = new Exception("Failed to convert one of the average duration to a double");
throw myex;
}
dr.Close();
dr.Dispose();
sql = "select avg(duration) as avgdur from " + dbname + " where startdate >= " + startdate.ToString("yyyyMMdd") + " and startdate <= " + enddate.AddMonths(+1).ToString("yyyyMMdd")
+ " and stopdate is not null and DONE is null";
cmd.CommandText = sql;
dr = cmd.ExecuteReader();
dr.Read();
double avgdrop;
if (!double.TryParse(dr["avgdur"].ToString(), out avgdrop))
{
Exception myex = new Exception("Failed to convert one of the average duration to a double");
throw myex;
}
dr.Close();
dr.Dispose();
sql = "select callstatus, count(*) as num from " + dbname + " where startdate >= " + startdate.ToString("yyyyMMdd") + " and startdate <= " + enddate.AddMonths(+1).ToString("yyyyMMdd")
+ " and stopdate is not null group by callstatus";
cmd.CommandText = sql;
dr = cmd.ExecuteReader();
int linenum = 3;
exl.WriteCell(column + linenum.ToString() + ":" + column + linenum.ToString(), total);
linenum++;
exl.WriteCell(column + linenum.ToString() + ":" + column + linenum.ToString(), entered);
linenum++;
exl.WriteCell(column + linenum.ToString() + ":" + column + linenum.ToString(), completed);
linenum++;
exl.WriteCell(column + linenum.ToString() + ":" + column + linenum.ToString(), abandoned);
int minutes = ((int)Math.Round(avgcompleted, 0) / 60);
int seconds = ((int)Math.Round(avgcompleted, 0) % 60);
string line = minutes.ToString() + ":" + seconds.ToString();
linenum++;
exl.WriteCell(column + linenum.ToString() + ":" + column + linenum.ToString(), line);
minutes = ((int)Math.Round(avgdrop, 0) / 60);
seconds = ((int)Math.Round(avgdrop, 0) % 60);
line = minutes.ToString() + ":" + seconds.ToString();
linenum++;
exl.WriteCell(column + linenum.ToString() + ":" + column + linenum.ToString(), line);
object[] zerofill = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
exl.WriteRange(column + "11:" + column + "38", zerofill);
while (dr.Read())
{
if (dr["callstatus"].ToString() == "00_SurveyInt")
linenum = 11;
if (dr["callstatus"].ToString() == "01_SurveyCode")
linenum = 12;
if (dr["callstatus"].ToString() == "02_Visit_Date")
linenum = 13;
if (dr["callstatus"].ToString() == "03_Visit_Time")
linenum = 14;
if (dr["callstatus"].ToString() == "04_Purpose_Visit")
linenum = 15;
if (dr["callstatus"].ToString() == "06.1_First_Impres")
linenum = 16;
if (dr["callstatus"].ToString() == "06.2_OV_SatB")
linenum = 17;
if (dr["callstatus"].ToString() == "06.3_OV_RecB")
linenum = 18;
if (dr["callstatus"].ToString() == "06.4_OV_Value")
linenum = 19;
if (dr["callstatus"].ToString() == "06.5_Trans_Time")
linenum = 20;
if (dr["callstatus"].ToString() == "06.5Service")
linenum = 21;
if (dr["callstatus"].ToString() == "06.6_Employee_Pro")
linenum = 22;
if (dr["callstatus"].ToString() == "06.7_Employee_Acc")
linenum = 23;
if (dr["callstatus"].ToString() == "06.8_Employee_Thank")
linenum = 24;
if (dr["callstatus"].ToString() == "06.9_Employee_Sat")
linenum = 25;
if (dr["callstatus"].ToString() == "06.9.1_Employee_WOW")
linenum = 26;
if (dr["callstatus"].ToString() == "06.9.2_Demographics")
linenum = 27;
if (dr["callstatus"].ToString() == "06.9.3_Gender")
linenum = 28;
if (dr["callstatus"].ToString() == "06.9.4_Age")
linenum = 29;
if (dr["callstatus"].ToString() == "07_Draw")
linenum = 30;
if (dr["callstatus"].ToString() == "13_Phone")
linenum = 31;
if (dr["callstatus"].ToString() == "12_Rules")
linenum = 32;
if (dr["callstatus"].ToString() == "11_ContestRules")
linenum = 33;
if (dr["callstatus"].ToString() == "08_Exit_System")
linenum = 34;
if (dr["callstatus"].ToString() == "10_Kicked")
linenum = 35;
if (dr["callstatus"].ToString() == "Repeat")
linenum = 36;
if (dr["callstatus"].ToString() == "Start")
linenum = 37;
if (dr["callstatus"].ToString() == "06_Instruc_1")
linenum = 38;
exl.WriteCell(column + linenum.ToString() + ":" + column + linenum.ToString(), dr["num"]);
}
}
}
}
Here are my expected results
From the first DB
00_SurveyInt 172
01_SurveyCode 641
02_Visit_Date 146
03_Visit_Time 18
04_Purpose_Visit 7
06.1_First_Impres 6
06.2_OV_SatB 64
06.3_OV_RecB 10
06.4_OV_Value 5
06.5Service 2
06.5_Trans_Time 5
06.6_Employee_Pro 14
06.7_Employee_Acc 10
06.8_Employee_Thank 2
06.9.1_Employee_WOW 5
06.9.3_Gender 4
06.9.4_Age 4
06.9_Employee_Sat 3
06_Instruc_1 4
07_Draw 4
08_Exit_System 1360
10_Kick 9
11_ContestRules 3
12_Rules 14
13_Phone 31
Repeat 1
Start 21
and these are the results the process is returning
Survey Intro 172
Survey Entry Code 641
Visit_Date 146
Visit_Time 18
Purpose_Visit 7
First_Impres 6
OV_SatBranch 64
OV_RecBranch 10
OV_Value 5
Trans_Time 5
Service 2
Employee_Pro 14
Employee_Acc 10
Employee_Thank 2
Employee_Sat 3
Employee_WOW 5
Demographics 0
Gender 4
Age 4
Draw 4
Phone 31
Rules 14
Contest Rules 3
Exit System 9
Kicked Out 0
Repeat 1
Start 21
Instructions 4
I cant figure out why these arent matching up if someone could help me identify the problem please.
modified on Thursday, July 23, 2009 1:43 PM
|
|
|
|
|