|
achandra007 wrote:
UINT TestThread(LPVOID pParam)
{
return ((CReadIntoSybaseDlg *)AfxGetApp())->RunThread();
}
You are doing complete nonsense here! AfxGetApp() retuns a pointer to the one-and-only CWinApp object. This has nothing to do with your dialog and the result of your cast is just "undefined".
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Thank you for politely replying to my question. Suprisingly, the "nonsense" works when I use global variables of type CDataset etc. But I won't waste your time in getting you to explain that. If you can answer my question (see the original post), then I thank you in advance. Otherwise, don't waste my time with these useless suggestions.
thanks
ashish
|
|
|
|
|
Ashish,
Why do you try to blame the experienced people that just want to help you?
Surprisingly it works is really the right term here! This is definitively a huge bug in your code which, as I wrote, results in undefined behaviour. Undefined beheaviour means that anything could happen: Even that it surprisingly seems to work, but just stops working if you change something at a complete different position in your code.
To make it short: This bug has a good chance to be the reason for your access violations!
Fix it, check what happens and if you have still problems post the code again. It would be very kind if you enclose it with <pre> and </pre> tags next time, so it will appear well formatted in the forum. This would make it much better readable and therfore increases your chances to get a no-"nonsense" answer.
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Daniel
I am not trying to blame anyone. I asked a question and I think you just got off about the code. I admit it may have bugs - that is why I am asking the questions. But read my original post and then read my reply to Wes Jones. If you can still help, then thanks in advance. Otherwise, there is no need to pontificate. I will learn without it as well.
thanks
ashish
|
|
|
|
|
Hi Ashish,
Not to be rude, but there are plenty of problems w/ the code.
The access violoation you are seeing is due to the fact that CYourApp does not have a RunThread() function.
When you call AfxGetApp() is is returning a pointer to a CWinApp derived class, which is really a pointer to your CYourApp class which the class wizard creates for you. The ptr returned by AfxGetApp() is totally unrelated to any instances of CReadIntoSybaseDlg. The reason it didn't blow up on you when you used global data is because there wasn't any code implicitly trying to access the 'this' pointer in the implementation of RunThread. Since you're casting the ptr to CReadIntoSybaseDlg, your tricking it into calling your CReadIntoSybaseDlg::RunThread function. Your new function is trying to access member data via the 'this' ptr, but since you've casted the pointer to an invalid type, the 'this' ptr is really invalid.
Here's the proper way to call it:
CReadIntoSybaseDlg::StartThreadFunc()
{
m_pThWorker = AfxBeginThread(TestThread, this);
}
UINT CReadIntoSybaseDlg::TestThread(LPVOID lpvParam)
{
CReadIntoSybaseDlg * pThis = reinterpret_cast<CReadIntoSybaseDlg*>(lpvParam);
ASSERT( pThis );
pThis->RunThread();
return 0;
}
Other things that would make your code a little nicer would be to rename the member variables w/ the m_ prefix.
I'd recommend that you, or anyone else reading this, read the book "Programming Windows Applications" by Jeffrey Richter, or even the earlier version of the book titled "Advanced Window Applications" or something like that.
Also, get a copy of the big red MFC book from Wrox press by Mike Blazncack (sp?).
Without knowing the rest of your code, you're probably going to be better of, performance wise, if you use a CCriticalSection instead of a CMutex.
I also want to warn you to be careful not to access the database objects from different threads at the same time, which is probably what your doing w/ the CMutex anyway. Bad things can happen if one thread's doing an insert and another's doing a rollback.
HTH,
-Wes
Sonork ID 100.14017 wtheronjones
|
|
|
|
|
Wes
Thanks a lot for the information. In fact, I have done exactly as you have said. I have also changed the cast to use AfxGetMainWnd() instead of AfxGetApp().
This is really my first multi threading application and I am having a few problems with it. My goal is to have 1 worker and 1 UI thread. Both of them are launched successfully now but now I am having trouble with using CDaoDatabase based calls. I call the GetTableDefInfo and loop through checking the lAttribute (to check whether its a user table or a system table). The call to GetTableDefInfo goes through once but at the second call, the execution gets stuck at DAO_CHECK(pDAOTableDef->get_ValidationRule(&V_BSTR(&var))); call in void CDaoDatabase::FillTableDefInfo(DAOTableDef* pDAOTableDef,CDaoTableDefInfo& tabledefinfo, DWORD dwOptions) call.
I am pretty sure its related to the change in my code (from single threaded to dual-threaded). Could you please help.
Thanks
ashish
|
|
|
|
|
Hi ashish,
Your function shouldn't cast to AfxGetMainWnd(), you should pass the this ptr to AfxGetMainWnd(). Your thread may work now, but that's only because this is probably a dialog based app where CReadIntoSybaseDlg happens to be your main window (AfxGetMainWnd() is returning a ptr to an actual CReadIntoSybaseDlg). You always want to know what parameter you're passing to your thread function, and AfxGetMainWnd isn't going to return a known type if you ever wanted to use this code in another program.
I don't have much experience w/ CDaoDatabase to know what the exact problem might be, but I suspect that maybe you're opening the record set in your worker thread, and moving through the record set in your main thread(or a similar scenario). If that's the case try to ensure that all access to the database related objects are taking place in the same thread because I suspect that CDaoDatabase doesn't like it if you're doing things from multiple threads. It's conceivable that MFC/CDaoDatabase is attaching itself to a CWnd object in your main thread since that's where it's probably being instantiated from. If MFC is attached to a CWnd in your main thread, and your main thread is blocking while waiting for a worker thread to finish something w/ the database, you could see a lockup condition.
Best advice would to be sure to do all your database accessing from the same thread that's using the db objects. Try doing all the processing in your main thread, and then try it again so that all the processing in the worker thread to see if it behaves differently.
Btw, Do you really need a worker thread for what you're trying to do? I use Sybase & I don't find the queries to take that long.
If you're designing your app so that the UI thread displays data when the worker thread signals that data is ready & your accessing the same db objects, & if CDaoDatabase really has an issue w/ being used this way, it's going to cause you to have to do some extra work.
-Wes
Sonork ID 100.14017 wtheronjones
|
|
|
|
|
Wes
Thanks for the advice. I will make the appropriate changes.
You may be right about CDaoDatabase. I am opening it in the main thread (Open call) and then passing the main processing function to AfxBeginThread so that all the processing (multiple databases are being used) can be done in the background. The reason I have to use two threads is that I need GUI control over the dialog window.
I read some of the DAO documentation and it does not support multiple threads. However, I had thought if I did everything in the worker thread, it should be OK. Apparently, it does not like being opened with the main thread and then being worked on by another. I will probably have to move the code around.
Thanks a lot
ashish
|
|
|
|
|
Wes,
On another note, since you mentioned you are using Sybase, I too am using Sybase but with the MFC ODBC classes. It is too slow, especially with inserts and updates. Any hints?
Thanks
ashish
|
|
|
|
|
Hey,
I don't find the ODBC to be slow at all for inserts & updates... I am using more of the ODBC API instead of CDatabase, but that's cause most of my classes work w/ CE (no CDatabase on CE). There are some things you can do to increase performance such as not using CRecordset::AddNew() and then CRecordst::Update to insert a new row. If you know the values, just write an insert statement... it's only one trip to the database instead of two, (unless you need retrieve the new primary key). If you're doing more than a certain # of inserts to the same table(a batch operation let's say), it's best to use a prepared statement & bound parameters at more of an API level than to use a bunch of single insert statements or using AddNew/Update. Just guessing, but i'd think that the odbc classes will be faster than the dao classes.
-Wes
Sonork ID 100.14017 wtheronjones
|
|
|
|
|
I meant the ODBC interface in MFC implemented through CDatabase. I find that to be slow. But its only slow with Sybase and not with SQL Server, which is my other data source.
thanks
ashish
|
|
|
|
|
In VS6 you could see a live memory-dump in a window. I can't find this feature in VC7. Is it left and hidden, or removed?
|
|
|
|
|
Debug -> Windows -> Memory -> pick on of 4 windows
CPUA 0x5041
Sonork 100.11743 Chicken Little
"So it can now be written in stone as a testament to humanities achievments "PJ did Pi at CP"." Colin Davies
Within you lies the power for good - Use it!
|
|
|
|
|
I am converting a UNIX application to Windows using VC++ and MFC. There are a large number of printf statements in the code, so I re-defined the printf function, with vsprintf, so that all text will go to a richedit control.
The problem I face is that when a data file is read, it is possible that one of the fields will have a "%" sign as part of its value. When this value is displayed, it looks as though vsprintf is behaving as documented and printing the value without the % sign. Does anyone know of an easy, efficient way to make sure the % sign is printed as well?
Thanks,
Shawn
|
|
|
|
|
Shawn Horton wrote:
Does anyone know of an easy, efficient way to make sure the % sign is printed as well?
I'm not sure what exactly do you want to achieve. You've mentioned that there are fields in data file and vsprintf replaces % sequences with actual values. Do you want to keep a percent sign before the value? If this is the case, try appending %% in front - this will result in one percent sign being printed.
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
Maybe this will help:
char data_name[DATANAMELEN];
read_function(data_name);
//data_name now contains the value "%recovered"
printf("we read in %s", data_name);
The printf statement to the Richedit window is now
we read in recovered
notice the missing %?
Maybe that is a bit clearer.
My hope is that I will not have to look for a % in character in each variable, and then insert a % in front of that.
Thanks for the help.
|
|
|
|
|
Shawn Horton wrote:
Maybe that is a bit clearer.
Totally clear now. I don't know about any format modifier which could cause [v]sprintf to literally copy % sign.
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
I should just post something like "Duh I am having a problem" on my first post, because the second one usually makes more sense.
|
|
|
|
|
If you're using MFC in your project, use CString::Format - it will work for you.
Tomasz Sowinski -- http://www.shooltz.com
What is "scratch" and why can everything be made from it?
|
|
|
|
|
Sounds like a bug in vsprintf
It surely should take everything that is passed literally as literals.
Or I am missing something here?
Maybe it is a feature, called somewhat like "recursive format substitution"...
What happens if you replace "%" with "%%" in your data_name?
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Actually, it was a bug in our re-defined printf. The function for the richedit control that we were using was expecting both a format specifier and a va_list, but we forgot the format specifier. Thus, when the function saw
%recovered, it saw an invalid format specifier (%r) and threw out the % like it said it would.
I hate when compilers do what you tell them to do instead of doing what you want them to do.
Thanks for the help.
Shawn
|
|
|
|
|
Shawn Horton wrote:
I hate when compilers do what you tell them to do instead of doing what you want them to do.
Yeah... After 40 years of science, computers are still stupid at all. Tons of work remaining for us developer folks
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
I get this error when using acmDriverEnum to enumerate all the different codecs on my system, this is the callback function:
BOOL WINAPI listCallback(HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport)
{
if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC)
{
ACMDRIVERDETAILS details;
details.cbStruct = sizeof(details);
acmDriverDetails(hadid, &details, NULL);
SendMessage(GetDlgItem(ghWnd, IDC_CODECS), LB_INSERTSTRING, 0, (LPARAM)details.szLongName);
}
return true;
}
In this routine i simply check if the current driver is a codec, and if it is i add the name of it to a listbox. The error happens when i have looped though all of the different codecs and the return true; statement has been executed. After that it jumps to some assembly code, and this is the stament it gives me the message after completing:
call dword ptr [ebp+8]
When that statement has been executed, the "User breakpoint called from code at 0x77f9f9df" message appears, and it jumps to this statement:
int 3
I've never experienced this message before and i haven't got a clue what it means.
All help appreciated.
-Rune Svendsen
|
|
|
|
|
This is an exception being thrown... Try review the call stack and get some other clues...
Concussus surgo.
When struck I rise.
|
|
|
|
|
Sorry for my ignorance, but what is the call stack and how to i review it?
Thanks.
|
|
|
|