Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / CLR / June 2006

Tip: Looking for answers? Try searching our database.

use SerialPort with raw device names -or- cancel pending read on FileStream

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Ben Voigt - 09 Jun 2006 17:10 GMT
The SerialPort class provided by Microsoft has some code like:
SerialPort.PortName set accessor
           if (value.StartsWith(@"\\", StringComparison.Ordinal))
           {
                 throw new
ArgumentException(SR.GetString("Arg_SecurityException"), "PortName");
           }

SerialStream constructor:
     if ((portName == null) || !portName.StartsWith("COM",
StringComparison.OrdinalIgnoreCase))
     {
           throw new
ArgumentException(SR.GetString("Arg_InvalidSerialPort"), "portName");
     }

I have USB device names that work great with the Win32 CreateFile... but
SerialPort chokes because of the arbitrary requirement imposed that serial
port names look like COMn.  Am I going to have to write a complete new
managed serial port interface?

I tried getting a SafeFileHandle from CreateFile and SetCommState,
SetCommTimeouts, and making it into a FileStream, and this works, but
asynchronous reads are acting dopey.  Obviously the SerialPort class does a
lot of stuff specially designed for serial ports and I don't get this with
FileStream.  I'm worried about my pending read request, because depending on
the timeouts specified sometimes I get a CancelledOperationException when I
close the serial port, but sometimes the operation stays pending... no
callback, no signalled event.
"Jeffrey Tan[MSFT]" - 12 Jun 2006 06:51 GMT
Hi Ben,

Thanks for your post!

Yes, Serial Port in Windows requires the port name to start with "COM". The
.Net2.0 SerialPort is not designed to work with USB device, it is used for
serial port.
Based on my experience, there is no build-in support for USB device in .Net
currently. I think you still have to p/invoke CreateFile Win32 API to open
the USB device for manipulation. Actually, SerialPort class internally also
encapsulates CreateFile.

Regarding your second question, I did not understand completely. Can you
provide some more background information? How do you do asynchronous read
operation in .Net?

Thanks!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Barry Kelly - 12 Jun 2006 08:41 GMT
> Regarding your second question, I did not understand completely. Can you
> provide some more background information? How do you do asynchronous read
> operation in .Net?

Ben said:

> I tried getting a SafeFileHandle from CreateFile and SetCommState,
> SetCommTimeouts, and making it into a FileStream, and this works, but
> asynchronous reads are acting dopey.

It would thus appear that he is using Stream.BeginRead().

-- Barry

Signature

http://barrkel.blogspot.com/

Ben Voigt - 12 Jun 2006 14:57 GMT
>> Regarding your second question, I did not understand completely. Can you
>> provide some more background information? How do you do asynchronous read
[quoted text clipped - 7 lines]
>
> It would thus appear that he is using Stream.BeginRead().

That's correct.  After setting EFileAttributes.Write_Through |
EFileAttributes.Overlapped in the CreateFile call, things are working more
smoothly.  There are still a lot of things done behind the scenes in
SerialPort, like time-sensitive instead of throughput-optimized buffering,
that I'll be having to figure out.

Basically, what I was seeing without EFileAttributes.Overlapped set was that
at stream close, the BeginRead would sometimes complete, invoking the
callback which threw a OperationCanceledException from EndRead, and
sometimes continue on.  This prevented me from Disposing the stream, because
the callback was sometimes still called much later.

With the Overlapped flag set, it seems that the callback is never called and
the IAsyncResult's event is not signalled.  I'm still trying to decide
whether I could have trouble if I close the stream while the callback is
executing on a worker thread...

I'm now thinking that I might need to ditch FileStream as well and do
everything directly with the Win32 API (I'll use C++/CLI instead of pinvoke
if I go this route) so I can use (for example) CancelIo.

Can someone explain to me how asynchronous I/O and thread pools interact?
Is it true that a thread pool is only used if the handle is associated to a
completion port, and that otherwise the callback is done as an APC in the
thread that issued the ReadFileEx request?  Does the .NET Framework use
alertable waits (it seems no, PeekMessage and GetMessage instead of
MsgWaitForYYYEx)?  An special considerations I should be aware of if I
replace Application.Run with my own MsgWaitForYYYEx loop (like modal dialogs
still using the framework message loop, etc.)?  I've done this with native
C++ before but not in a managed application.

I'm strongly considering keeping this application single-threaded and
working on re-entrancy instead of thread safety... it is targeted at an
embedded device so I won't have HyperThreading/multi-cores to drive a need
for additional threads.

> -- Barry
"Jeffrey Tan[MSFT]" - 13 Jun 2006 07:46 GMT
Hi Ben,

Thanks for your feedback!

Based on my knowledge, doing asynchronized I/O operation requires opening
the device with FILE_FLAG_OVERLAPPED flag. This is stated in CreateFile
MSDN documentation:
"If this flag is not specified, then I/O operations are serialized, even if
the calls to the read and write functions specify an OVERLAPPED structure."

>Can someone explain to me how asynchronous I/O and thread pools interact?
Currently, this type of internal design information is not public
documented yet. However, you can still use Reflector to view the FCL
source, so you can explore it youself.
Based on my basic research, FileStream.BeginRead method internally
encapsulate with ReadFile Win32 API instead of ReadFileEx. So
FileStread.BeginRead  does not use alertable I/O for asynchronized I/O
operation.

Since .Net FCL does not p/invoke CreateIoCompletionPort API internally,
.Net does not use I/O completion port for asynchronized I/O operation
either.

If you really want to design high performance and scalable application in
.Net, you may p/invoke CreateIoCompletionPort to implement ICOP yourself,
please refer to the article below for some guide:
"IOCP Thread Pooling in C#"
http://www.devarticles.com/c/a/C-Sharp/IOCP-Thread-Pooling-in-C-sharp-Part-I
/

Finally, the sample below provided a sample implementation of asnychronous
SerialStream:
"SerialStream - use the serial port as a Stream"
http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=fcba7
fc5-666e-4eb0-863f-0045b0c79ec7

Hope this helps!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Ben Voigt - 13 Jun 2006 23:29 GMT
> Hi Ben,
>
[quoted text clipped - 16 lines]
> FileStread.BeginRead  does not use alertable I/O for asynchronized I/O
> operation.

Yes, I've been looking, mostly at Windows.Forms.Application+ThreadContext
which is the main loop, which has no support for APCs.  Wondering if maybe
there was a really good reason for that.

At any rate, it doesn't look like I'd be able to set up an alertable message
loop on the main thread because the first modal dialog called up from any
component is going to stall the main message loop.  But there's this
MessageLoopCallback delegate which is public but miniscule documentation...
more hours with Reflector in my future.

> Since .Net FCL does not p/invoke CreateIoCompletionPort API internally,
> Net does not use I/O completion port for asynchronized I/O operation
[quoted text clipped - 24 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
"Jeffrey Tan[MSFT]" - 14 Jun 2006 06:32 GMT
Hi Ben,

Thanks for your feedback!

MsgWaitForMultipleObjectsEx is used to place the calling thread in
alertable state where this thread contains message loop(create windows).
Yes, .Net Winform main GUI thread did not build this feature in its message
loop. Is there any special reason that you have to queue APC to the main
GUI thread? I think you'd better use other non-GUI thread for APC callback.
In non-GUI thread, other APIs can be used to jump into alertable state:
SleepEx, SignalObjectAndWait, WaitForMultipleObjectsEx, or
WaitForSingleObjectEx function etc..

.Net System.Threading.ThreadPool class can be used to manage thread pooling
and asychronous I/O operations. You might want to give it a try. For more
information, please refer to the 2 articles below:
"Programming the Thread Pool in the .NET Framework"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/ht
ml/progthrepool.asp
"The CLR's Thread Pool"
http://msdn.microsoft.com/msdnmag/issues/03/06/NET/

Hope this helps!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Ben Voigt - 14 Jun 2006 15:52 GMT
> Hi Ben,
>
[quoted text clipped - 7 lines]
> GUI thread? I think you'd better use other non-GUI thread for APC
> callback.

Because I want only one other thread -- to run a watchdog timer.  If I have
multiple threads, then (1) my objects can no longer trigger events to GUI
components, (2) all objects need to become thread-safe, and (3) I need a
whole host of watchdogs.

I'm not worried about keeping the GUI responsive while stuff happens in the
background, if anything in the system hangs, the user had best be able to
tell -- this will be a medical device running XP embedded.  Deployment will
include some nasty physical conditions, so failures will happen, and the
last thing I want are silent failures.

What I am wanting is asynchronous notification of arriving data.  Sockets
have WSAAsyncSelect (which, using messages, will work with
Application+ThreadContext's PeekMessage/GetMessage loop), timers can send
messages too.  I'm looking for something equivalent for serial port i/o.  I
thought APCs would be the trick.  Do you know of something better?  Maybe if
I keep the extra threads to I/O only, I can keep the processing
single-threaded.  I'll just use a thread-safe linked list for data transfer,
and post a windows message when activity occurs.

I had good luck in unmanaged C++ with acquiring some data, then passing a
pointer to the buffer to PostMessage for processing and display... but I
suspect this will wreak havoc with the CLR and result in my buffers being
garbage collected during transit... back to the standard heap then.

Does InterlockedCompareExchange work with gc handles?

> In non-GUI thread, other APIs can be used to jump into alertable state:
> SleepEx, SignalObjectAndWait, WaitForMultipleObjectsEx, or
> WaitForSingleObjectEx function etc..
>
> Net System.Threading.ThreadPool class can be used to manage thread pooling
> and asychronous I/O operations. You might want to give it a try. For more
... but I'm not looking for throughput.
> information, please refer to the 2 articles below:
> "Programming the Thread Pool in the .NET Framework"
[quoted text clipped - 14 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
Barry Kelly - 14 Jun 2006 16:32 GMT
> Because I want only one other thread -- to run a watchdog timer.  If I have
> multiple threads, then (1) my objects can no longer trigger events to GUI
> components,
[...]
>  I'll just use a thread-safe linked list for data transfer,
> and post a windows message when activity occurs.

Sorry for butting in, but: the idiom in .NET for communicating with the
GUI thread from a background thread is to use Control.Invoke or
ISynchronizeInvoke.Invoke (all controls implement ISynchronizeInvoke)
e.g. in C# 2.0:

 control.Invoke((EventHandler) delegate { control.TriggerEtc(); });

-- Barry

Signature

http://barrkel.blogspot.com/

Ben Voigt - 14 Jun 2006 21:46 GMT
>> Because I want only one other thread -- to run a watchdog timer.  If I
>> have
[quoted text clipped - 10 lines]
>
>  control.Invoke((EventHandler) delegate { control.TriggerEtc(); });

I'm aware of this, it appears to be a blocking cross-thread call, like DCOM
calls into an STA or SendMessage.  It appears that Control.Invoke uses
PostMessage followed by ManualResetEvent.WaitOne.  This makes it both slow
and prone to deadlock.  It breaks deadlocks by enforcing a 1000ms timeout
that the documentation does not mention.

> -- Barry
Barry Kelly - 15 Jun 2006 06:51 GMT
> >  control.Invoke((EventHandler) delegate { control.TriggerEtc(); });
>
[quoted text clipped - 3 lines]
> and prone to deadlock.  It breaks deadlocks by enforcing a 1000ms timeout
> that the documentation does not mention.

Yes, it is synchronous. There's always BeginInvoke, of course.

-- Barry

Signature

http://barrkel.blogspot.com/

"Jeffrey Tan[MSFT]" - 15 Jun 2006 08:08 GMT
Hi Ben,

Thanks for your feedback!

> (3) I need a whole host of watchdogs.
What do you mean by this point?

> I'm not worried about keeping the GUI responsive while stuff happens in the
> background, if anything in the system hangs, the user had best be able to
> tell
It seems that you are not worried about hanging in GUI thread.
Unfortunately, currently, .Net winform GUI thread does not include
MsgWaitForMultipleObjectsEx API, so we can not queue APC on main GUI
thread.

Doesn't FileStream.BeginWrite method meet your need? What problem do you
meet while using it? You'd better give a read to the "Asynchronous I/O
Operations" section in the article I provide in the original reply.

Regarding the p/invoke memory issue, I am not familiar with it. Based on my
experience, if you allocate the buffer with Marshal.AllocCoTaskMem to alloc
the memory, it will not be GCed during usage.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Ben Voigt - 15 Jun 2006 16:17 GMT
> Hi Ben,
>
> Thanks for your feedback!
>
>> (3) I need a whole host of watchdogs.
> What do you mean by this point?

Every thread needs to have a watchdog, which is basically just an integer
variable.  Every thread will periodically load its watchdog with some value,
say 10, from either a timer message or other main processing loop.  An
independent high-priority thread wakes periodically, calls
InterlockedDecrement on each watchdog.  Any watchdog that reaches zero
indicates a thread stuck performing a subtask, due to deadlock, or
synchronous I/O on a broken network connection, or logic that allowed an
infinite loop for some particular input data, or whatever other reasons
cause programs to hang.

>> I'm not worried about keeping the GUI responsive while stuff happens in
> the
[quoted text clipped - 8 lines]
> meet while using it? You'd better give a read to the "Asynchronous I/O
> Operations" section in the article I provide in the original reply.

It's not writing, that can be synchronous since I won't be sending large
amounts of data.  I can use BeginRead, with the callback, but I believe the
callback takes place from the threadpool?  Which leaves me with the same
synchronization issues.  Also, I see no way to cancel a BeginRead call.
With direct WinAPI calls, there's CancelIO.

> Regarding the p/invoke memory issue, I am not familiar with it. Based on
> my
> experience, if you allocate the buffer with Marshal.AllocCoTaskMem to
> alloc
> the memory, it will not be GCed during usage.

The only issue is my lack of expertise concerning p/invoke.  I know C++ so
I've only used IJW.

> Thanks.

Thanks for all your patient help.

> Best regards,
> Jeffrey Tan
[quoted text clipped - 5 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
"Jeffrey Tan[MSFT]" - 16 Jun 2006 03:54 GMT
Hi Ben,

Thanks for your feedback!

Oh, I think I understand your requirement much better now. It seems what
you want to achieve is placing the pure I/O operation in the background
thread pool thread, while get the result callback in the main GUI thread,
not from a worker thread.

Yes, based on my debugging, I found that the .Net CLR internal mechanism
invokes the BeginWrite/Read callback routine in another thread pool thread,
not the main GUI thread. Below is the callback stack I got with managed
symbol debugging:

0372f9d8  010a0317 [DEFAULT] [hasThis] Void
AsynchronousTest.Form1.EndWriteCallback(Class System.IAsyncResult)
 at [+0x17] [+0xa]
g:\program\winform\2006\6-16\asynchronoustest\form1.cs:92
0372fad8  7923c069 [FRAME: GCFrame]
0372fbd0  7923c069 [FRAME: ECallMethodFrame] [DEFAULT] [hasThis] Object
System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(Cla
ss System.Reflection.MethodBase,SZArray Object,Object,I4,Boolean,ByRef
SZArray Object)
0372fbf4  79af513e [DEFAULT] [hasThis] Class
System.Runtime.Remoting.Messaging.IMessageCtrl
System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(Class
System.Runtime.Remoting.Messaging.IMessage,Class
System.Runtime.Remoting.Messaging.IMessageSink)
0372fc5c  79aea95f [DEFAULT] Void
System.Runtime.Remoting.Proxies.AgileAsyncWorkerItem.ThreadPoolCallBack(Obje
ct)

Note: the top stack frame is the callback routine I defined in my
application.

Based on my research, the current .Net implementation does not embed the
function of callback to GUI thread, so if you want to achieve this, you
have to p/invoke the APC message loop yourself. However, because of the
complexibility of .Net winform message loop, there is no easy way of
reinventing the wheel yourself. Also, I am not if there is any potential
problem regarding interoperation between your implementation of message
loop and .Net Form/Control classes. I think the simplest workaround is
changing your code to be thread-safe and allowing multithreading in your
main application, or you may have to use synchronous I/O.

.Net FileStream class does not support CancelIO function, you have to
p/invoke CancelIO API to get this done. Please refer to the articles below
for a sample:
"Use P/Invoke to Develop a .NET Base Class Library for Serial Device
Communications"
http://msdn.microsoft.com/msdnmag/issues/02/10/NETSerialComm/
"Serial Communications : The .NET Way"
http://www.codeproject.com/dotnet/DotNetComPorts.asp

P/invoke related issues can be got most professional help in the
microsoft.public.dotnet.framework.interop newsgroup. Anyway, the 2 articles
below both demonstrate the usage of p/invoke, which may give you a good
sample.

I know that there are many aspects you have concern regarding .Net CLR/FCL,
if you feel it a uncomfortable, I recommend you feedback these concern in
the MSDN Product Feedback Center below:
http://connect.microsoft.com/Main/content/content.aspx?ContentID=2220

Thanks for your understanding and patient.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Ben Voigt - 16 Jun 2006 20:04 GMT
> Hi Ben,
>
[quoted text clipped - 4 lines]
> thread pool thread, while get the result callback in the main GUI thread,
> not from a worker thread.

Yes, exactly (minus the words thread pool).

> Yes, based on my debugging, I found that the .Net CLR internal mechanism
> invokes the BeginWrite/Read callback routine in another thread pool
[quoted text clipped - 32 lines]
> changing your code to be thread-safe and allowing multithreading in your
> main application, or you may have to use synchronous I/O.

I've been writing a C++/CLI library.  The event-driven interface I'm
exposing lends itself rather well to a message-passing architecture.  I've
got a threadsafe queue used to pass requests to the worker thread (custom
ThreadProc, sits and calls WaitForSingleObjectEx).  An event is set each
time an item is added to the queue, thus waking the worker thread.
Responses are posted to a windows message queue in the GUI thread (my
managed class derives from NativeWindow to catch these and will be firing
events within the next couple hours).

The managed class calls CreateFile to open the port, then GetCommState and
GetCommTimeouts to initialize its internal data structures, then places the
handle in a request.  The handle will never be used from the GUI thread
again.  The objects passed using the request queue and message queue are
reference counted.

The only shared variables are the threadsafe queue and reference counts,
which all use the Interlocked family of functions.  There is no contention
possible, although InterlockedCompareExchangePointer could fail on a
multiprocessor system and have to retry.  Other than the
InterlockedCompareExchangePointer loop, the GUI thread performs no waits
whatsoever.

I will be able to use this same worker thread for all serial port
connections (up to a dozen on this product collecting data from different
medical devices, plus internal system status), and I can also handle other
notifications as well:

By adjusting the timeout parameter to WaitForSingleObjectEx, I can implement
a large number of timers.  By using WaitForMultipleObjectsEx, I can add
socket I/O with WSAEventSelect.

> Net FileStream class does not support CancelIO function, you have to
> p/invoke CancelIO API to get this done. Please refer to the articles below

Additional caveat: p/invoke CancelIo can't be combined with
BeginRead/EndRead, since they execute on a thread pool thread, and CancelIo
must be called from the thread issuing the ReadFile(Ex) call.  This
situation will improve somewhat with CancelIoEx in Vista.  I will submit
some feedback that the SerialPortAsyncResult should provide a managed
interface to the CancelIoEx function for Vista, because otherwise the
LPOVERLAPPED structure identifying the operation is not available to
consumers.

> for a sample:
> "Use P/Invoke to Develop a .NET Base Class Library for Serial Device
[quoted text clipped - 26 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
Ben Voigt - 16 Jun 2006 20:28 GMT
>> Hi Ben,
>>
[quoted text clipped - 87 lines]
> the LPOVERLAPPED structure identifying the operation is not available to
> consumers.

Posted here:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=
137076

and here:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=
137088


>> for a sample:
>> "Use P/Invoke to Develop a .NET Base Class Library for Serial Device
[quoted text clipped - 26 lines]
>> This posting is provided "AS IS" with no warranties, and confers no
>> rights.
"Jeffrey Tan[MSFT]" - 19 Jun 2006 09:50 GMT
Hi Ben,

Thanks for your feedback!

I am glad you finally got a workaround regarding this issue.

Regarding your 2 feedback requests, I still have some comment:

1,  "P/Invoke CancelIo will not work, because the CancelIo call must be
made from the thread which requested the operation, but the implementation
makes the call from the thread pool."

Yes, CancelIo API will only cancel all the pending input and output (I/O)
operations that are issued by the calling thread for a specified file
handle. Can you tell me what leads you to believe that it is the ThreadPool
thread who makes the call to the I/O when using BeginRead? Based on my
research with Reflector, the call stack to ReadFile  win32 API looks like
this:

Win32Native.ReadFile(which p/invokes to Kernel32!ReadFile)
FileStream.ReadFileNative
FileStream.BeginReadCore
FileStream.BeginRead

So it seems that the thread calling FileStream.BeginRead is the thread who
issues the I/O read operation. You can use the CancelIo in the same thread
as FileStream.BeginRead to cancel the I/O operations. If I have
misunderstood you, please feel free to tell me, thanks.

2. "Because Windows Forms uses PeekMessage/GetMessage, functions requiring
alertable waits such as waitable timers and ReadFileEx/WriteFileEx cannot
be used from a GUI thread."

Yes, just as we previous discussed, winform message loop does not
encapulate the alertable I/O waiting with MsgWaitForMultipleObjectsEx.
Also, FileStream.BeginRead calls back the callback_proc in the ThreadPool
thread. However, in your scenario, your callback_proc needs to execute the
post-I/O processing in the GUI thread because of the non-thread safe watch
dog. I think this is your key problem.

Is it possible for you to use Control.BeginInvoke method in the Thread Pool
callback_proc to queue an asynchronous work to the GUI thread? With this
way, you can forward the callback work to the GUI thread and will eliminate
the thread safe issue.

Hope this helps!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Ben Voigt - 19 Jun 2006 16:13 GMT
> Hi Ben,
>
[quoted text clipped - 25 lines]
> as FileStream.BeginRead to cancel the I/O operations. If I have
> misunderstood you, please feel free to tell me, thanks.

Ok.  I may have gotten confused between the paths for asynchronous
(BeginRead/EndRead) I/O with files opened with/without the overlapped flag.

> 2. "Because Windows Forms uses PeekMessage/GetMessage, functions requiring
> alertable waits such as waitable timers and ReadFileEx/WriteFileEx cannot
[quoted text clipped - 6 lines]
> post-I/O processing in the GUI thread because of the non-thread safe watch
> dog. I think this is your key problem.

Well, actually the watchdog will the threadsafe, but it will only watch
particular threads.  Tell me, what happens if the application gets into a
state causing the threadpool callbacks to stall (either a resource deadlock,
or walking a singly-linked list that got crossed back on itself, etc)?  My
assumption is that the OS would create a new thread for each callback until
the threadpool limit is reached, and then callbacks would stop, the app
would allocate additional resources for each new I/O request which could
never be freed.  The main application may timeout on the data, but it will
be difficult to distinguish from an unresponsive (powered off, disconnected)
serial device.  This seems to be a serious drawback of the threadpool.

I intend to ship an app where this isn't possible, but at least during
development, being able to reliably detect this condition will be very
helpful.  My team is doing software and hardware design for the processor
subsystem as well and hardware and firmware for many of the devices... and
in my experience, when problems occur, they may be very difficult to
reproduce, or may only appear after the system runs for some time, causing
an integer overflow or such.  Knowing where the failure lies is a big step
toward fixing it.

As I am implementing a single worker thread for my I/O, I can specify a
timeout in the WaitForSingleObjectEx call, and reset the watchdog each time
through the loop.  Thus if the watchdog timer runs out, I can start some
recovery action (probably halt all other threads, dump data to disk as
necessary, write a minidump, and restart the process).  If I was using
threadpool, managing watchdogs would be a very tricky operation (probably
requiring synchronized access to some list of running threads, which adds
the potential to involve the watchdog thread in a deadlock).

> Is it possible for you to use Control.BeginInvoke method in the Thread
> Pool
> callback_proc to queue an asynchronous work to the GUI thread? With this
> way, you can forward the callback work to the GUI thread and will
> eliminate
> the thread safe issue.

This probably works quite well under nominal conditions.

> Hope this helps!

You've been very helpful.  Thanks for taking the time to understand my
problem space.

> Best regards,
> Jeffrey Tan
[quoted text clipped - 5 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
"Jeffrey Tan[MSFT]" - 20 Jun 2006 04:28 GMT
Hi Ben,

You are welcome.

Yes, FileStream.BeginWrite/Read queues the asynchronous I/O to OS, then
.Net ThreadPool thread will execute your provided callback procedure.

Note: .Net ThreadPool manages a pool of spawned threads which are live with
ThreadPool, so whenever the callback is executing, .Net will not create a
new thread, it just reuses one of the ThreadPool live thread to execute the
callback procedure. If your callback procedure blocks in the execution,
threadPool can not reuse the first ThreadPool thread, and it has to use
another live thread in the pool to execute the second callback procedure.
So if all the callback procedure blocks in the execution, your application
callback may use out of the ThreadPool threads.

As we can see in "ThreadPool.GetAvailableThreads" method in MSDN:
"If there are no available threads, additional thread pool requests remain
queued until thread pool threads become available."

So if you used out of the ThreadPool threads, there maybe a great
performance issue in your application threading model, especially when you
are queuing a lot of asynchronous I/O requests. You'd better not block too
long in callback procedure.

>Knowing where the failure lies is a big step toward fixing it
You can use ThreadPool.GetAvailableThreads method to determine the free
thread in ThreadPool. This method may give you some hint whether the
unresponsive is caused by bad serial device or pooling issue.

If you really have to block in the ThreadPool callback, you have 2
workarounds:
1. Spawn a new thread to execute the reminding work and exit the callback.
2. Queue an asynchronous request to the GUI thread with
Control.BeginInvoke. By doing this, the callback work has been forwarded to
the GUI thread in MessageLoop. Note: if you are doing this, the GUI thread
may have a lot of work to do, and it may hang in the work, which gives a
non-responsible UI to the customer.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Ben Voigt - 20 Jun 2006 15:43 GMT
> Hi Ben,
>
[quoted text clipped - 30 lines]
> If you really have to block in the ThreadPool callback, you have 2
> workarounds:

Thanks.  Looks like ThreadPool.GetAvailableThreads would have provided some
of the information I was looking for.  But, I'm already done implementing
the single worker-thread version, so I don't think I'll be trying to use the
ThreadPool.  My concerns about callbacks blocking aren't from a design
perspective, but rather an attitude of "bugs happen, especially during
development" and a desire to be able to find out exactly what's going on.
Also, I work on medical systems for NASA, and sooner or later our device
will take a radiation hit.  When that happens, I want to maximize the chance
of detecting it and, in case of a soft hit, recover.

Basically radiation causes the same set of problems as an unstable power
supply, but affects CPU and memory more than I/O buses:
* soft hit = data corruption (knocked some electrons around, changing the
capacitive charge in a DRAM cell or CPU register)
* hard hit = permanent physical damage (ionization created a conducting
path, allowing a large current to flow and breaking down a capacitive
structure, like a FET)
* severely reduced product life

These effects only happen when the device is powered up (soft hits are
corrected during bootup, hard hits require current from the power supply),
and there's spare equipment, so the worst thing is a silent failure.

> 1. Spawn a new thread to execute the reminding work and exit the callback.
> 2. Queue an asynchronous request to the GUI thread with
[quoted text clipped - 15 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
"Jeffrey Tan[MSFT]" - 22 Jun 2006 04:48 GMT
Hi Scott,

Oh, I was not aware that there are so much background information in your
design. Yes, you may live with your current single worker-thread design.  
:-)

Additionally, regarding your original SerialPort port name starts with
"\\.\" issue, I have helped you to forward it to the developer team, below
is the feedback:
"True but we do not allow you to use ¡°\\.\¡± device names anywhere else in
the framework. You can¡¯t even use these names with FileStream even though
you could call CreateFile.

This is done to reduce the risk and the attack surface area associated with
SerialPort and at the time we did not have any information that was an
important scenario. Though we have gotten feedback like your from at least
one other customer and we are considering supporting this in a future
release."

Currently, I think you have to p/invoke CreateFile to workaround this issue.

Hope my effect makes sense to you.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
"Jeffrey Tan[MSFT]" - 15 Jun 2006 08:14 GMT
If I am not clear in my reply, I mean that you may use
FileStream.BeginWrite method to start the asynchronized I/O operation in
GUI thread and get the callback result in UserCallback method. Does it meet
your need? Please feel free to feedback your concern regarding it. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Ben Voigt - 12 Jun 2006 15:08 GMT
> Hi Ben,
>
[quoted text clipped - 4 lines]
> Net2.0 SerialPort is not designed to work with USB device, it is used for
> serial port.

I guess I need to clarify:  The device is a serial port.  It implements the
serial port device interface GUID_DEVINTERFACE_COMPORT and appears in the
ports listing of the Device Manager.  It does not matter to Windows whether
the serial port is connected via a PCI bus or USB bus, whether it is found
by the ACPI or USB plug-and-play enumerator.  The device even receives a
"COMn" alias.  But "COMn" is not given to me by RegisterDeviceNotification,
the plug-and-play name is.  The "COMn" mapping can change as devices are
plugged and unplugged, and by reboots.  If I start hunting around in the
registry for the mapping, I will have a race condition.  I want to use only
the PnP device name that comes with RegisterDeviceNotification because it
has the device serial number embedded and I therefore know what device is
connected.

> Based on my experience, there is no build-in support for USB device in
> .Net
[quoted text clipped - 18 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
"Jeffrey Tan[MSFT]" - 13 Jun 2006 07:12 GMT
Hi Ben,

Thanks for your feedback!

Sorry, I do not have much experience on native device related serial port
design. If your device has implemented the serial port device interface and
its name is not started with "COM", I think you have to p/invoke Win32 APIs
to do the I/O operations. Anyway I will try to perform an internal
consulting regarding why SerialPort requires port name with "COM". I will
feedback any further findings here.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
"Jeffrey Tan[MSFT]" - 14 Jun 2006 04:20 GMT
Hi Scott,

Sorry for letting you wait.

Below is our FCL team's feedback:

We require the port name to start with COM because we call CreateFile by
appending the port name ¡°\\.\¡± and we did not want to allow the user to
pass in strings like ¡°PHYSICALDRIVE0¡± and do bad things with devices like
this.

I am not sure that this will work with your specific device but the mapping
between device names and com ports is in the registry at:
HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM. You might be able to
enumerate these entries to find the COM port number that goes with your
device.

Hope this makes sense.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Ben Voigt - 14 Jun 2006 21:34 GMT
> Hi Scott,
>
[quoted text clipped - 7 lines]
> like
> this.

I think the correct behavior would be to prepend \\.\ only if the portname
starts with "COM", and use all other names as presented.  It's not the
responsibility of the FCL to determine what is "too dangerous"; once you
start down that track you might as well not sell compilers or run any code
not written by Microsoft..... oops, I guess that's what the Intel Secure
Computing initiatives are.  Will we next see FileStream weighed down with a
bunch of code checking that you don't open "%SYSTEMDRIVE%\boot.ini" in write
mode, or "%SYSTEMROOT%\System32\Config\*" where the machine registry hives
are stored?  CreateFile doesn't perform any of these checks, it just
enforces access control and file locking.  If \\.\PHYSICALDRIVE0 has an ACL
giving me access, the FCL should let me open it.

For those people who pass around tainted data without checking it, and run
with the SYSTEM account, there could be a SafeOpen that restricts the
parameters and DeviceOpen that uses the parameter exactly as passed.  Really
though, much better to put the effort into doing a perl-style taint check
and generating compile-time errors for unvalidated user inputs, ala how
FxCop checks that public methods test for null arguments.

> I am not sure that this will work with your specific device but the
> mapping
> between device names and com ports is in the registry at:
> HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM. You might be able to
> enumerate these entries to find the COM port number that goes with your
> device.

The entries there have the form \Device\VCP128
What I get from RegisterDeviceNotification (via WM_DEVICECHANGE) looks like:
\\?\ftdibus#vid_0403+pid_6010+75ouhtg7aa#0000#{86e0d1e0-8089-11d0-9ce4-08003e301f73}
The port number is stored under
HKLM\SYSTEM\CurrentControlSet\Enum\FTDIBUS\VID_0403+PID_6010+75OUHTG7AA\0000\DeviceParameters\PortName,
but that path is not accessible through SetupDiOpenDeviceInterfaceRegKey or
SetupDiGetDeviceRegistryProperty and is probably manufacturer-specific.

> Hope this makes sense.
>
[quoted text clipped - 7 lines]
> This posting is provided "AS IS" with no warranties, and confers no
> rights.

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.