Possible improvements to Asyncronous Pattern?

  • Thread starter Thread starter sb534dan
  • Start date Start date
S

sb534dan

I've always found it beneficial that win form component events always
callback into the UI thread (as oppose to a worker thread). The UI
client code is never exposed to the worker thread. I find this very
desirable, as this prevents resource sharing problems from within the
callback method. This guarantees that all of the client code runs
within its own thread.

With the upcoming release of .NET 2.0, various classes have been
introduced to aid in the development and usage of components providing
asynchronous operations. This is great for components (classes
implementing IComponent or deriving from System.Component). But for
normal (non component) classes, this functionality isn't provided.

When implementing the traditional .NET async pattern for normal classes
(
http://msdn.microsoft.com/library/d...ml/cpconasynchronousdesignpatternoverview.asp
), the callback is always run in a worker thread context. Therefore,
exposing the client code to a different thread.

I've considered implementing similar functionality to the .NET 2.0
component async functionality, but for normal classes. To do this. A
queue would have to be introduced for every thread in a program.
(Something akin to a traditional windows message queue).

This, I feel would eliminate the need for my class to expose its worker
thread to the client.

I'd love to hear any comments on this. My reasoning and potential
implementation maybe flawed. But I really would like an overall
opinion.

Dan.
 
I've always found it beneficial that win form component events always
callback into the UI thread (as oppose to a worker thread). The UI
client code is never exposed to the worker thread. I find this very
desirable, as this prevents resource sharing problems from within the
callback method. This guarantees that all of the client code runs
within its own thread.

With the upcoming release of .NET 2.0, various classes have been
introduced to aid in the development and usage of components providing
asynchronous operations. This is great for components (classes
implementing IComponent or deriving from System.Component). But for
normal (non component) classes, this functionality isn't provided.

When implementing the traditional .NET async pattern for normal classes
(
http://msdn.microsoft.com/library/d...ml/cpconasynchronousdesignpatternoverview.asp
), the callback is always run in a worker thread context. Therefore,
exposing the client code to a different thread.

I've considered implementing similar functionality to the .NET 2.0
component async functionality, but for normal classes. To do this. A
queue would have to be introduced for every thread in a program.
(Something akin to a traditional windows message queue).

This, I feel would eliminate the need for my class to expose its worker
thread to the client.

I'd love to hear any comments on this. My reasoning and potential
implementation maybe flawed. But I really would like an overall
opinion.

If you're not in a UI context, why do you want the callback to occur on the
calling thread?

David
 
If you're not in a UI context, why do you want the callback to occur on the
calling thread?

David

If it doesnt callback on the calling thread, then the client is able to
"access data at the same time", as the code in the callback. i.e. the
client code is exposed to two threads (instead of just the one, in the
case of win forms).
 
If it doesnt callback on the calling thread, then the client is able to
"access data at the same time", as the code in the callback. i.e. the
client code is exposed to two threads (instead of just the one, in the
case of win forms).

But if you don't want simultaneous access, why are you using a background
thread at all?

And what is the calling thread doing that can be interrupted to process a
callback? And what is the mechanism for interupting the calling thread?

If the calling thread becomes idle and wants to wait for the background
operation to complete to complete, it can just call
IAsyncResponse.WaitHandle.WaitOne().

David
 
What you need is not a queue but a "message thread" class, waiting for
message and dispatching them.
I don't think it needs to be an API class as it is:
1. simple enough to program
2. really depends on the specific of the application

about 2, I would say that myControl.BeginInvoke(aDelegate) is a GUI specific
mechanism, which work well with the GUI event thread.

But how is it to work with any other thread?
I mean, common, a thread is just a unit of code execution, it doesn't have
concept such as 'event' or 'message'

Anyway here is a pseudo code MessageThread implementation for you (from the
top of my head).

class MessageThread<T>
{
Thread runner;
LinkedList<MsgInfo> list = new LinkedList<MsgInfo>();
ManualResetEvent waiter;
class MsgInfo
{
public MsgInfo(EventHandler<T> eh, object sender, EventArgs<T> e)
{
this.eh = eh;
this.sender = sender;
this.args = e;
}
public EventHandler<T> eh;
public object sender;
public EventArgs<T> arg;
}

public MessageThread()
{

runner = new Thread(MessageLoop);
waiter = new ManualResetEvent(false);
}

public void Run()
{
runner.Run();
}
void MessageLoop()
{
while(running)
{
waiter.Wait();
MsgInfo msg = null;
lock(list)
{
if(list.Count == 0 || !running)
waiter.Reset();
else
msg = list.RemoveHead();
}
if(msg != null)
msg.eh(msg.sender, msg.args);
}
}

public void Dispatch(EventHandler<T> eh, object sender, EventArgs<T> e)
{
lock(list)
{
list.AddTail(new MsgInfo(eh, sender, e));
waiter.Set();
}
}
}
 
I believe you (I mean sb534dan, the original poster) don't fully understand
what's a thread.
maybe you should investigate the matter further?
there is nothing really complex with them....
 
I think perhaps im not explaining myself clearly enough. I would like
the caling thread to say the following:
"Start reading from this socket (but dont block).
Inform me once you've read some data by calling this callback.
I require that this callback only be called, when im not processing
anything (my thread is idle)".

Something like this (very rough psuedo code):

class Socket
{
// Begins reading. (doesnt block).
public void BeginReading(Delegate callback)
{
// Starts thread to process read, and returns straight after.
// When worker thread completes work. It will queue the correct
delegate to the calling threads queue.
}
}

class Client
{
Socket _socket = new Socket();

Queue _queue = new Queue();

// Constructor
public Client()
{
// Init the (thread-safe) queue for this thread (holds an array of
delegates).
_queue = new Queue();

// Init socket
_socket = new Socket();

// Start reading from socket (non-blocking).
_socket.BeginReading(new Delegate(OnReadCompleted))

// Process main application loop
MainLoop();
}

public void MainLoop()
{
// Loop forever (note that exit functionality is not shown)
while ( _queue.WaitOne())
{
Delegate handler = _queue.Dequeue();
// Call the handler (i.e. OnReadCompleted)
handler();
}
}

// This is called on the client thread!...not on a worker thread.
// the client can access any of its member data and not have to worry
// ...if this were called *whenever*, the client maybe in another one
of its methods, accessing the shared data.
public void OnReadCompleted()
{
}
}
 
1st you don't call into a thread.
a thread is either terminated or on a handle.Wait() instruction in the
middle of a function.

the GUI thread is a special thread, it's looping! (infinitely) and it does
accept new event too be processed (through an invisible queue).
if your thread should behave like that why don't you use the MessageThread I
write some pseudo code about earlier in this thread?

2ndly, you work with either of the above mentionned thread and you want to
"post" your delegate call into their queue.
you'll have to use 2 method!
the AsyncDelegate, which would post the message to this (special) thread's
queue
in C# 2.0 it could be onde in one line
myStream.BeginRead(buffer, offset, count, delegate(IAsyncResult ar){
myEvThr.Dispatch(myStream, ar); }, myStream);

where myEvThre is the MessageThread I wrote about earlier, in an other
answer to your questions.
 
Lloyd said:
1st you don't call into a thread.
a thread is either terminated or on a handle.Wait() instruction in the
middle of a function.

Yes. strictly you are correct. I should have wrote "I would like
the calling CODE to say the following...etc"

the GUI thread is a special thread, it's looping! (infinitely) and it does
accept new event too be processed (through an invisible queue).
if your thread should behave like that why don't you use the MessageThread I
write some pseudo code about earlier in this thread?

I only saw your pseudo code, after posting my own. I wouldnt have
bothered If I had. Both implementations show the concept im trying to
explain.
2ndly, you work with either of the above mentionned thread and you want to
"post" your delegate call into their queue.
you'll have to use 2 method!
the AsyncDelegate, which would post the message to this (special) thread's
queue
in C# 2.0 it could be onde in one line
myStream.BeginRead(buffer, offset, count, delegate(IAsyncResult ar){
myEvThr.Dispatch(myStream, ar); }, myStream);

where myEvThre is the MessageThread I wrote about earlier, in an other
answer to your questions.

Thanks for your implementation, and your tip about the up-coming c#
code.
However, implementation specifics is not what i posted about.

Its the concept I wanted to talk about. As you correctly mentioned,
its a main application thread which bahaves like the windows GUI thread
(fed by messages).

....can anyone else see the advantage of async call-backs occuring on
the client thread?....would the following be true?:

IF:

1. An entire (client) application could be written based open the
above one thread (application running in a big loop that re-acts to
events) AND

2. Whenever the application wished to perform in asynronous operation,
it could do so, calling a class which supported those operations making
use of the said architecture.

THEN...

The application writer, would *never* have to worry about threading
issues, because ALL of the application code, he has written, runs in
ONE thread.

Note, that any threading complexity is in the classes
providing the ayncronous operations. The client doesnt have to worry.
 
I hardly see your point, to tell the truth....

After much reading and reading of your post I think what you believe is the
following:

You believe that if AsuncCallback could be made to callback in the main
thread your application would be thread safe by default and you won't have
to worry, is that right?

Let me tell you: it's complete rubbish!

If you call (in the main thread) you stream while it's performing it's async
read/write, it will get corrupted. End of discussion. No matter what kind of
'callback architecture' you've got.
 
oops... pressed CTRL+ENTER accidentally...

Anyway, on the other hand, if this other thread bother you, dont use
AsyncCallback but

IAsyncResult ar = myStream.BeginRead(....);

// somethings.......

check completion
if(ar.IsCompleted)
doSomething()

so it's all in the main thread, you see!
but it's not thread safe at all!

you don't write it explicitely, but certainly you understand that the read
method is currently executing in an other thread, don't you?
don't perform other operation on the stream!
 
Yes of course the stream can be corrupted. Its instance members are
not thread-safe. But this architecture stops the client corrupting its
*OWN* data.

// Example 1
// Normal class.

Class Application
{
List<int> _intArray = new List<int>() = { 0, 1, 2, 3, 4 };

Stream _stream = new Stream();

public void Main()
{
_stream.BeginRead(StreamCallback,
...,
.etc)

// call back may occur before during this...causing
// client data corruption.
for (int i = 0; i < _intArray.Length(); i++)
{
Console.WriteLine(_intArray);
}
}

private void StreamCallback()
{
// Remove all ints.

// Because this can occur at anytime
// i.e. in a stream worker thread...
// a client may corrupt its own data.

while (_intArray.Length() > 0)
{
_intArray.RemoveAt(0);
}

}
}

// Example 2.
// Same class as above using callback architecture.

class Application : CallBackArchitecture
{
List<int> _intArray = new List<int>() = { 0, 1, 2, 3, 4 };

Stream _stream = new Stream();

public void Main()
{
_stream.BeginRead(StreamCallback,
...,
.etc)


// Can do this and not worry.
// Callbacks will occur on the same thread as this one.
for (int i = 0; i < _intArray.Length(); i++)
{
Console.WriteLine(_intArray);
}
}

private void StreamCallback()
{
// Remove all ints.

// This occurs on the clients thread.
// No possiblity of client data corruption.

while (_intArray.Length() > 0)
{
_intArray.RemoveAt(0);
}

}
}
 
Dan,

You could use the same approach that Microsoft used when designing the
System.Timers.Timer class. That class has a property called
SynchronizingObject that accepts an ISynchronizeInvoke interface. When
the timer has a synchronizing object set it invokes the callback on the
thread hosting that object, otherwise it invokes the callback from the
thread pool. Forms and Controls implement ISynchronizingInvoke so the
pattern works well for what you're after.

Brian
 
Thankyou Brian,

Just the sort of feedback i was looking for. I'lll look into
ISynchronizeInvoke.
Cheers.
 
Back
Top