08-05-2005 04:30 AM
////////////////////// MyDialog.h
class
CMyDialog : public CDialog{
..........
public
:ViStatus OnMyRead( CNiVisaEvent& event );
protected
:CNiVisaSession *m_Session;
CNiVisaJobId m_ReadJob;
public
:afx_msg
void OnBnClickedRead();...........
};
////////////////////// MyDialog.cpp
........
BOOL CMyDialog::OnInitDialog()
{
CString csName = "ASRl1::INSTR";
// COM-Port 1CNiVisaEventHandlerId eventId;
m_Session =
new CNiVisaSession( csName, VisaNoLock, 5000 );m_Session->SetAttribute( VisaTimeout, VisaTimeoutInfinite );
m_Session->SetAttribute( VisaSerialEndIn, (uInt16)VisaEndNone );
m_Session->SetAttribute( VisaTerminationChar, (uInt16)0 );
m_Session->SetBufferSize( VisaSerialInputBuffer, (uInt32)5000 );
// Event-Handlerm_Session->InstallEventHandler( VisaEventIoComplete,
*
this,OnVisaEventHandler(CMyDialog, OnMyRead),
eventId );
m_Session->EnableEvent( VisaEventIoComplete, VisaHandler );
return true;}
// Start Asynchron-Read
void
CMyDialog::OnBnClickedRead(){
//m_Session->Read( (ViBuf)m_cBuffer, 20, m_ReadJob ); // 20 Bytesm_Session->Read( (ViBuf)m_cBuffer, 700, m_ReadJob );
// 700 Bytes}
// Callback-Handler for Asynchron-Read
ViStatus CMyDialog::OnMyRead( CNiVisaEvent& event )
{
// process Read()-Data from m_cBuffer return VisaSuccess;}
...............
08-05-2005 07:29 AM
I found out, that the current problem is caused inside my Event Handler by the following statements:
// Callback-Handler for Asynchron-Read
ViStatus CMyDialog::OnMyRead( CNiVisaEvent& event )
{
// display the results
UpdateData( false );
m_slideLager11.SetValue(m_cZeichen);
After processing the received data, I would like to update the dialog controls to show the results (slider control ...).
Why do the statements UpdateData() and m_slide.SetValue() cause runtime errors ?
If I make the controls update by this statements outside of the Event Handler it works.
Is there any possibility to make the update inside of the Event Handler ?
Another problem:
The asynchronously read() returns immediately inside of the dialog. But if I close the dialog, before the job is done, the program is blocked (for about 15 seconds). I cannot make any input (choose another dialog ...) and I cannot close the program (no reaction if I try).
I supposed, the asynchronously job is killed, if I use the Terminate()-function in the dialogs destructor like this:
CMyDialog::~CMyDialog()
{
......
}
It doesn't work. With or without the Terminate()-statement, the program is blocked after closing the dialog before the asynchronously job is done. I tried also inside of the OnCancel()-function, but without success.
Do you have any idea why ?
Does anybody have some small code example which shows completely the asynchronously read() from the beginning to the correct termination, so that the program is not blocked in any way ?
Thanks a lot
Hannes
08-05-2005 11:55 AM
Can you tell me what runtime error the calls to UpdateData and SetValue are causing?
User interface controls typically must be accessed only from the thread on which they were created. When you create an event callback ofr VISA, it is very unlikely that that callback occurs on the UI thread - so updating controls from within it is not likely to work. The Measurement Studio C++ controls are designed so that, by default, they ARE accessible from multiple threads. The call to UpdateData, though, is occuring on the dialog class - which has no such guarantee. This might be the cause of the problem. Why are you calling UpdateData?
Also, in order to properly handle asynchronous reads and writes,you need to enable IO Completion events and register and appropriate callback for the event - this is the event that fires when the read or write completes. The JobId that the Read method returns is used to identify a particular read async event that completed.
The asynchronous read also tries to read into the buffer you supply when you call read - if that buffer is being deleted before the asynchronous operation terminates, you're going to run into some problems as well - for instance, if the lifetime of that buffer is shorter than the lifetime of the asynchronous operation. It appears from your code that you're using a member variable of the dialog box - so if the dialog is closed and destroyed while an async operation is still running, that would be a bad thing.
When you say that the call to Terminate doesn't work, can you tell me what IS happening? Are you getting an exception?
I'm having a hard time figuring out where to point you on this, because I don't think I really understand the architecture of your application - is all of this VISA serial IO going on in a dialog box that is launched from your main application window? If so, perhaps we need to separate the buffer, session, and async operation lifetime management from the lifetime of the dialog box.
08-05-2005 02:01 PM
Hallo Glenn,
thanks for your quick answer.
I start at the end of your questions:
The architecture of my test application is very simple. I have created a doc / view project with only one dialog, which is launched from the main window (by menue button). In this dialog, I would like to receive serial data, which are continuously coming. It is necessary to get data blocks in real time (9600 Baud). Between the blocks the data processing and display can be made.
After closing the dialog, I cannot close the program properly (even not with the call to Terminate), if the asynchronous job is not finished. I get no exception, but it just happens nothing for a long time of about 15 seconds. Then the program is closed.
Maybe this architecture is not the best to handle my application ?
I started with that simple dialog and the doc / view architecture because I thought, that should be an easy test environment.
In the final program I need sevaral dialogs to generate several views of the continuously incoming data.
I have an old program, which was developd in LabWindows and worked very fine. I used the "InstallComCallback"-function. This Handler can be set to a threshold value of incoming bytes. If more bytes are in the serial buffer, the callback function is triggered. In that function, the data processing, display and storage is done. After completion, I flush the serial buffer and the callback function is triggered the next time after receiving more bytes than the threshold value. Between the callback triggers, the program is not blocked. The user can change the scaling of diagram controls for example. Closing of the program is also no problem.
I'm looking for a mechanism like that in Measurement Studio !
The data receiving and storage should always work in the background. Meanwhile the user should have the possibility to make inputs to the program (choose several views and so on). The data processing, display and storage must go automatcally without user action.
I'm calling UpdataData() to update some Edit-Controls with new values.
The runtime error also occurs by updating the slider-control (m_slide.SetValue() 😞
"Debug Assertion Failed, File winocc.cpp, line 374" : ASSERT(m_pCtrlSite != NULL);
Regards Hannes
08-08-2005 10:08 AM
08-10-2005 03:21 AM
Hallo Glenn,
thanks for your answer. Meanwhile I got the program to work with lifetime management between the OnCancel()-function and the EventHandler-Callback.
I still have one problem:
I only can finish the program, if there are data coming until the callback is finished. Inside the callback there are several synchronously reads to follow the continuously incoming bytes. The "SerialAnyCharReceivedEvent" is only used as a trigger to start the callback. If the data stream is stopped during a read, the callback will never end. I cannot work with any timeout condition, because the data stream can be stopped for a "long time" (2 days...) and after the data are coming again, the program must continue without any user input. Therefore I set the Timeout to "infinite". On the other hand, it must be possible to finish the program, if there are no data coming.
Therefore I think, I need the asynchronously read. The read must be terminated, if the user wants to finish the program before all data bytes of the read are received.
As I told you before, I tried to terminate the asynchronously read job, but it didn't work.
Can you tell me, how to terminate the asynchronously read job inside of the dialog (ore anywhere else) ?
Do you have some example code, that shows what to do ?
Regards
Hannes
08-10-2005 11:44 AM
08-11-2005 09:25 AM
I will check that in future.
In the moment, I changed my application to use the VisaBytesSerialAttribute in the way you suggested.
That works properly in the moment.
Thanks for your help
Hannes