|
Hey? What? Errmmm, not at all sure what you are saying or what problem you are experiencing and need help with.
Steve Jowett
-------------------------
It is offen dangerous to try and see someone else's point of view, without proper training. Douglas Adams (Mostly Harmless)
|
|
|
|
|
I wrote a "widget" to report sales data, etc. I need to make some calculations based on business days to date this month. Business days are Mon-Fri, minus any holidays. Holidays are defined in my.settings, using a string collection. The function below iterates through the days of the current month until it reaches today. For each iteration, it checks to see if the day is a weekday, then checks to see if it is listed in my.settings.holidays. If it is a weekday, and not a holiday, the counter is incremented. If it is a holiday I receive a message "Holiday". This works exactly as I expect on my dev machine. However, when running the widget on any other machine, the "IF" statement that checks the holidays never evaluates to true. Any ideas anybody? Am I missing an import statement?
Protected Overridable Function CountBusinessDays() As Integer
Dim BusDays As Integer
Dim RefMonth As Integer = Month(Now)
Dim CalcDate As Date = DateSerial(Year(Now), Month(Now), 1)
Do While Month(CalcDate) = RefMonth
Dim wkday As Integer = Weekday(CalcDate)
If wkday <> 1 And wkday <> 7 Then
If Not My.Settings.Holiday.Contains(CalcDate.ToString) Then
BusDays = (BusDays + 1)
Else : MsgBox("Holiday") 'For testing....
End If
End If
If CalcDate = Date.Today Then Exit Do
CalcDate = CalcDate.AddDays(1)
Loop
Return BusDays
End Function
We use Visual Studio 2005, and have .Net framework 3.5 installed on all machines.
|
|
|
|
|
How is your 'Holiday' setting originally getting populated? I am wondering if maybe the string you expect simply is not in the User.Config on the "other" machine(s). Have you checked the user.config on the other machines to see if that setting is populated?
|
|
|
|
|
Excellent thing to check. However, I have already checked that the holidays are there. The 'Holidays' are pre-populated with some default values at build time. The user can change them at will. The settings are there, I verified this with:
For each st as string in My.Settings.Holidays
msgbox(st)
Next
The messages show the correct dates, which reflect any changes made on the specific machine. I also
have user settings for fore and back colors, window location, etc. which are always applied correctly.
I also tried aggregating all the holidays into one string and search it using 'InStr'. Once again, this worked fine on the dev machine but not others.
Does the problem lie in the fact that I am comparing a "date.tostring" with a "string"? But it does work on the dev machine....
|
|
|
|
|
Does the problem lie in the fact that I am comparing a "date.tostring" with a "string"? But it does work on the dev machine....
That may very well be the problem, since the 'ToString()' can do a default conversion to different formats on different machines. Since you know what the date format used is within the 'Holiday' setting, you should ensure that you convert to that format with ToString. For example, if your Holiday date string format is YYYYMMDD, you could do CalcDate.ToString("yyyyMMdd") in your conditional statement.
|
|
|
|
|
Thanks! That is it. I had tried '.toshortdatestring' and a few others, and none worked. For some reason I never thought of simply formatting the string.
|
|
|
|
|
I have been working on this code for quite awhile and cant seem to get it right. Its supposed to worked like
1. Click button to load csv(appended to datagrid1)
2. Click another button to export the edited csv.(not working at all, not sure where to start)
currently my datagrid codes are
<br />
button load_csv click<br />
Dim strConnection As System.Data.OleDb.OleDbConnection<br />
Dim myPath As String = "c:\testing.csv"<br />
<br />
Try<br />
<br />
'Dim objDataSet As System.Data.DataSet<br />
Dim objAdapter As System.Data.OleDb.OleDbDataAdapter<br />
<br />
strConnection = New System.Data.OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source='" & myPath & " '; " & "Extended Properties=Excel 8.0;")<br />
objAdapter = New System.Data.OleDb.OleDbDataAdapter("select * from [sheet1$]", strConnection)<br />
objDataSet = New System.Data.DataSet<br />
objAdapter.Fill(objDataSet)<br />
DataGrid1.DataSource = objDataSet.Tables(0).DefaultView<br />
strConnection.Close()<br />
<br />
Catch ex As Exception<br />
<br />
Dim er As String<br />
<br />
strConnection.Close()<br />
<br />
End Try
i believe i do have to declare a global variable for datagrid1 as the export function needs it.
modified on Monday, July 28, 2008 2:03 PM
|
|
|
|
|
zzsoulzz wrote: Click another button to export the edited csv.(not working at all, not sure where to start)
Provide your code for this part, the other code you provided looks right. Is it populating the datagrid?
"The clue train passed his station without stopping." - John Simmons / outlaw programmer
"Real programmers just throw a bunch of 1s and 0s at the computer to see what sticks" - Pete O'Hanlon
|
|
|
|
|
yes it is populating for my datagrid1
here is the code for export to csv
Dim dataSource As DataTable = DirectCast(DataGrid1.DataSource, DataTable)<br />
<br />
Dim currentRow As New System.Text.StringBuilder<br />
Dim entireFile As New System.Text.StringBuilder<br />
<br />
'Write the column names as headers for the file<br />
For Each column As DataColumn In dataSource.Columns<br />
currentRow.Append(""""c & column.ColumnName & """"c & ",")<br />
Next<br />
<br />
'Add the current line to the entire file StringBuilder<br />
entireFile.Append(currentRow.ToString)<br />
<br />
'Write each data row to the file StringBuilder<br />
For rowIndex As Int32 = 0 To dataSource.Rows.Count - 1<br />
currentRow = New System.Text.StringBuilder<br />
For Each column As DataColumn In dataSource.Columns<br />
currentRow.Append(""""c & dataSource.Rows(rowIndex)(column.ColumnName).ToString & """"c & ",")<br />
Next<br />
entireFile.Append(currentRow.ToString)<br />
Next<br />
<br />
'Write the contents of the entireFile StringBuilder to a file.<br />
Dim sw As New System.IO.StreamWriter("C:\Temp\DataGrid.csv")<br />
<br />
sw.Write(entireFile.ToString)
|
|
|
|
|
Why not open the file in the beginning and just write the lines one at a time? Is the StreamBuilder creating the csv data correctly?
"The clue train passed his station without stopping." - John Simmons / outlaw programmer
"Real programmers just throw a bunch of 1s and 0s at the computer to see what sticks" - Pete O'Hanlon
|
|
|
|
|
having that code allows others to input their own csv instead of specifying one.
the current export isnt exporting at all.
it returns
<br />
An unhandled exception of type 'System.InvalidCastException' occurred in BScanner.exe<br />
<br />
Additional information: Specified cast is not valid.<br />
for this line
Dim dataSource As DataTable = DirectCast(DataGrid1.DataSource, DataTable)
|
|
|
|
|
Hi,
I'm not a VB 2005 coder. I'm forced to use VB because the SDK that came with a device only supports VB.
I have to send 65536 floating values to this device. I store these values in a double array and when I need to send them to the device I use stringbuilder in a thread to build the string, as following.
For i = 0 To 65535
System.Threading.Thread.Sleep(1)
ArbString.Append(", ")
ArbString.Append(ArbData(i).ToString("0.0000"))
worker.ReportProgress(i)
Next
Despite using stringbuilder the whole takes around 40 seconds to complete. Am I doing something wrong here or is there something I can do to speed the whole thing up?
TIA
|
|
|
|
|
shortest time you can sleep is 13 ms if i recall correctly.
so 65536 * 13 = 851 sec if Im not too tired after my vacation :P
|
|
|
|
|
Hi,
1.
you can't get an accurate delay like that. Sleep causes a thread switch, and it could take any
number of milliseconds before your thread is allowed back in.
for more accurate timing stuff, you may want to read my timers article.
2.
if you want to measure StringBuilder.Append performance, make a loop that contains just that;
no threading stuff, no backgrounders, no GUI access. Loop it many many times and use a StopWatch
to measure it. (BTW my article does not mention StopWatch, it was based on NET 1.x and StopWatch
got introduced with 2.0; I am working on an update).
3.
If you want maximum StringBuilder performance, make sure it has sufficient capacity right from
the start. If you don't, it will outrun its capacity, allocate a new and larger buffer
(typ. twice as large) and copy what it had so far. Your example needed around 500K characters, so
about two megabytes of unnecessary data copying have occured. Of course, using string instead of
StringBuilder would have been much much worse.
|
|
|
|
|
Hi Luc,
Thanks for your effort.
1. The sleep(1) is there todo just that, to give other threads a chance to get some execution time in the scheduler.
2. I didn't measure it using any timers, just the watch on my wrist. The thing is I did build a nice little GUI around this whole process with a nice animation and a progressbar but it still seems weird to me that this whole process would take so much time to complete.
3. You might be onto something there, how do I preallocate the size of a stringbuilder?
|
|
|
|
|
I'm wondering why the sleep command is there? If you are just building a string, then do you need the sleep?
Also, reporting progress - I would try cut that down a lot! Perhaps using:
if (i mod 255)=0 then
worker.ReportProgress(i)
end if
This will report progress a lot less often, so fewer thread switches etc.
|
|
|
|
|
Hi Jasey9,
I have a few other threads running and the sleep(1) is just there to force the scheduler to switch threads so this one doesn't hog up all the execution time. Give other threads a chance so to speak.
Thanks I'll try your suggestion.
|
|
|
|
|
frylord wrote: System.Threading.Thread.Sleep(1)
Might be the culprit. I understand you may need a delay to the device, but during each iteration?
"The clue train passed his station without stopping." - John Simmons / outlaw programmer
"Real programmers just throw a bunch of 1s and 0s at the computer to see what sticks" - Pete O'Hanlon
|
|
|
|
|
Hi Paul,
It's not the sleep(1). The reason I know this is at first I expected this process to complete within a "reasonable" (not letting the user think the GUI got stuck) amount of time so I did this process under a button. Then when I noticed it's taking a lot of time to complete I put it in a thread with a nice GUI and such.
The sleep(1) is just there to force the scheduler to switch threads to give other threads some execution time as well.
Thanks for the effort.
|
|
|
|
|
frylord wrote: sleep(1) is just there to force the scheduler to switch threads to give other threads some execution time as well.
Looking at what Luc said, it makes sense, and the other poster's idea of using the mod might help.
"The clue train passed his station without stopping." - John Simmons / outlaw programmer
"Real programmers just throw a bunch of 1s and 0s at the computer to see what sticks" - Pete O'Hanlon
|
|
|
|
|
frylord wrote: The sleep(1) is just there to force the scheduler to switch threads to give other threads some execution time as well.
That does not make sense to me. Either the code is running in the GUI thread, and Sleep is a no-no;
or it runs in another thread, and you should put Sleep calls when they are necessary. You don't need
to help Windows, Windows will reschedule threads when it feels like it, even when
they don't cooperate. You don't expect a single while(1){} to hog the CPU for 100% and
forever, do you? (I am not implying you should do such things, just saying Windows does not care
about the meaning of your code).
Just pointing out Windows will switch away from any thread, in favor of another thread:
- with higher priority
- with same priority, out of fairness concerns
- and even occasionally with lower priority, to maybe escape from an accidental deadlock situation.
BTW: the last paragraph applies more to desktop versions, and less to server versions of Windows.
|
|
|
|
|
Well to be honest I don't know. Somehow my college teachers indoctrinated the idea that you should block your current thread so other threads can get some execution time aswel. The same idea continued into my university years and has sticked with me ever since and I've also seen the same in alot of online tutorials and examples. I think this idea of blocking one thread to give others a chance could be left over from the days when schedulers weren't as complex.
|
|
|
|
|
Hi,
if you have a lot of work that needs to be done but is not urgent, then you should organize things
in such a way that other, possibly more urgent things, can be done first. This is accomplished
either by using a thread with lower priority (recommended when available, it is on Windows),
or by "throttling" yourself, i.e. forcing the OS to try and do something else from time to time.
Now giving away the CPU after copying 8 characters is not a good idea, since a thread switch would
cost anywhere between 10 and 1000 times as much as the work you are doing. So the reduction by
255 as suggested by one reply is appropriate.
But as I said before, it only takes some 40 msec althogether, so don't bother; just don't do it
in your own GUI thread!
BTW: GUI threads have a slightly higher priority than other threads at "normal priority" anyway.
And yes, it would be different on simpler operating systems, as well as on real-time environments,
as could be found in embedded systems.
|
|
|
|
|
Hi,
I have read your message again, and feel a need to add some:
- I am not sure the elapsed time is caused by the code you have shown, it merely loads a StringBuilder,
it does not send anything to your external device;
- if your connection is say a serial port (you did not specify) then it is operating at some baud rate;
when we assume 115200 Bd then that means a maximum of some 13K characters per second; so your
500K characters would require 35 seconds at least. So the transmission itself could be the bottleneck.
- if your (serial?) port uses some kind of handshaking (you did not specify), then maybe
it is the device itself that can't run any faster, and is telling the PC to slow down. In this case
the target device is the bottleneck.
If any of the above applies, it becomes unclear why you feel the need to first build a huge
string. You might consider outputting the numbers one by one, or a few KB at a time.
Finally, are you sure you need the comma-space combination? If one of those characters is redundant,
it takes one-eight of the bandwidth (that is 5 seconds in your case). And if you see a chance to
turn the assumed serial port to 7-bit instead of 8-bit that would shave of another 5 seconds or so
(this requires both sides to agree on it). Also, maybe the device does not need the 0.0000 format;
if it does not care about trailing zeroes, why send them?
|
|
|
|
|
Hi Luc,
Once again thank you.
The device is connected through a TCP/IP connection.
The thing is that the SDK doesn't allow for sending the data one by one, you need to send it in one line. So what I do is build the string I need to send using string builder and then afterwards send it using the SDK function and the stringbuilder ToString function.
I think I'll have to explain a bit more about the device, atleast I owe you that much I guess. The so called "device" is a arbitrary waveform generator. here's an excerpt from the manual.
You can download from 1 point (a dc signal) to 65,536 (64K) points per
waveform. You can download the points as floating-point values. Use the SendArbData function to
download floating-point values from -1.0 to +1.0.
And here's the bit on how the data should be.
The following statement shows how to use the SendArbData function to
download seven points to volatile memory.
SendArbData("1, .67, .33, 0, -.33, -.67, -1")
So basically it wants me to format a huge string of 65536 data points in CSV format and then use the SendArbData function to send it to the device.
|
|
|
|