473,411 Members | 1,991 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,411 software developers and data experts.

Asynchronous Threading Issue

Hi all. I'm relatively new to delegates and asynchronous threading and am
running into an issue. I need to asynchronously call a method (which I'm
doing with a delegate and BeginInvoke) and from the callback method, or at
some point after the EndInvoke has been called to end the asynchronous
operation I need to asynchronously call a different method.

I really want to keep this event based and use delegates and callbacks
rather than loop until completed, as there will be many instances of this
process running at the same time in parallel and I don't want to strain
resources.

The results are that the first method seems to be called multiple times.
Here's an example of the results of the test code I'll paste below ...

12:48:12 PM: 3932: Entering Main
12:48:12 PM: 3932: Calling Test1 asnchronously
12:48:12 PM: 2064: Entering Test1
12:48:12 PM: 2064: Exiting Test1
12:48:12 PM: 2064: Entering Test1Callback
12:48:12 PM: 2064: Calling EndInvoke in Test1Callback
12:48:12 PM: 2064: Calling Test2 asynchronously
12:48:12 PM: 2064: Exiting Test1Callback
12:48:12 PM: 2064: Entering Test1
12:48:12 PM: 2064: Exiting Test1
12:48:12 PM: 2064: Entering Test2Callback
12:48:12 PM: 2064: Calling EndInvoke in Test2Callback
12:48:12 PM: 3932: Exiting Main
12:48:14 PM: 2064: Entering Test2Callback
12:48:14 PM: 2064: Calling EndInvoke in Test2Callback

Notice that Test1 is called multiple times. Ideally I would like to see this
executed once. This is the behaviour I'm trying to rectify. Can anyone
suggest what I'm doing wrong? Here's the code for the test app (please be
sure to cut the sample code and results from any replies to this post to
keep the size down).

Thanks in advance, Sam.

VB CONSOLE APP CODE ...

Imports System
Imports System.Diagnostics

Module MainModule

Private Delegate Sub Test1Delegate()
Private Delegate Sub Test2Delegate()

Sub Main()
Console.WriteLine(String.Format("{0}: {1}: Entering Main",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))
Console.WriteLine(String.Format("{0}: {1}: Calling Test1 asnchronously",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))

Dim method As New Test1Delegate(AddressOf Test1)
Dim result As IAsyncResult = method.BeginInvoke(New
AsyncCallback(AddressOf Test1Callback), method)

Do Until result.IsCompleted
'
Loop

Console.WriteLine(String.Format("{0}: {1}: Exiting Main",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))
Console.ReadLine()
End Sub

Private Sub Test1()
Console.WriteLine(String.Format("{0}: {1}: Entering Test1",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))
Console.WriteLine(String.Format("{0}: {1}: Exiting Test1",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))
End Sub

Private Sub Test1Callback(ByVal ar As IAsyncResult)
Console.WriteLine(String.Format("{0}: {1}: Entering Test1Callback",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))
Console.WriteLine(String.Format("{0}: {1}: Calling EndInvoke in
Test1Callback", DateTime.Now.ToLongTimeString(),
AppDomain.GetCurrentThreadId))

Dim method As Test1Delegate = DirectCast(ar.AsyncState, Test1Delegate)
method.EndInvoke(ar)

Console.WriteLine(String.Format("{0}: {1}: Calling Test2
asynchronously", DateTime.Now.ToLongTimeString(),
AppDomain.GetCurrentThreadId))

Dim method2 As New Test2Delegate(AddressOf Test2)
Dim result As IAsyncResult = method.BeginInvoke(New
AsyncCallback(AddressOf Test2Callback), method)

Console.WriteLine(String.Format("{0}: {1}: Exiting Test1Callback",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))
End Sub

Private Sub Test2()
Console.WriteLine(String.Format("{0}: {1}: Entering Test2",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))
Console.WriteLine(String.Format("{0}: {1}: Exiting Test2",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))
End Sub

Private Sub Test2Callback(ByVal ar As IAsyncResult)
Console.WriteLine(String.Format("{0}: {1}: Entering Test2Callback",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))
Console.WriteLine(String.Format("{0}: {1}: Calling EndInvoke in
Test2Callback", DateTime.Now.ToLongTimeString(),
AppDomain.GetCurrentThreadId))

Dim method As Test2Delegate = DirectCast(ar.AsyncState, Test2Delegate)
method.EndInvoke(ar)

Console.WriteLine(String.Format("{0}: {1}: Exiting Test2Callback",
DateTime.Now.ToLongTimeString(), AppDomain.GetCurrentThreadId))
End Sub

End Module
Jul 21 '05 #1
9 1761
Hi Sam,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that there is something wrong with the
multi-thread app, in which Test2 never get called. If there is any
misunderstanding, please feel free to let me know.

Based on the code you have provided, it seems there is a mistake in the
Test2CallBack. In your code, you called method.BeginInvoke to start the
thread. However, it has to be method2, because method's thread function has
been set to Test1. The following is the modified code. HTH.

Console.WriteLine(String.Format("{0}: {1}: Calling Test2
asynchronously", DateTime.Now.ToLongTimeString(),
AppDomain.GetCurrentThreadId))

Dim method2 As New Test2Delegate(AddressOf Test2)
Dim result As IAsyncResult = method2.BeginInvoke(New
AsyncCallback(AddressOf Test2Callback), method)

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

Jul 21 '05 #2
Silly me. Should have triple checked the sample code. I didn't call
method2.BeginInvoke and as a result it doesn't rally highlight the problem
I'm having at all.

The threading issue I'm trying to work through revolves around the
System.Net.Sockets.Socket.BeginConnect method. My understanding of async
callbacks is that if I use a callback function it will execute on a
different thread to the main thread. However, if I use a callback function
in the BeginConnect method and note the thread it would appear to be on the
main thread. This might not be the actual problem, but after that call
everything in my app goes haywire.

I want to call BeginConnect so that I try to connect without holding up
execution on the main thread, but if there's an error connecting I want to
retry automatically for x number of times. On success I want to then raise a
public event to notify success. I can get my code to perform the connection
attempt, and retries and after actually connecting it executes the public
"Connected" event once (traced to confirm), but when I trace the handler of
the event I see it has actually executed the number of times I tried to
connect.

Anyone else seen this? I use a similar form of code to the example I
attached earlier (which seems to perform correctly after fixing the bug :))
which leads me to suspect the way BeginConnect operates ???

Suggestions? Examples of using BeginConnect and retries with callbacks
instead of loops?

Sam.

"Kevin Yu [MSFT]" <v-****@online.microsoft.com> wrote in message
news:3w**************@cpmsftngxa10.phx.gbl...
Hi Sam,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that there is something wrong with the
multi-thread app, in which Test2 never get called. If there is any
misunderstanding, please feel free to let me know.

Based on the code you have provided, it seems there is a mistake in the
Test2CallBack. In your code, you called method.BeginInvoke to start the
thread. However, it has to be method2, because method's thread function has been set to Test1. The following is the modified code. HTH.

Console.WriteLine(String.Format("{0}: {1}: Calling Test2
asynchronously", DateTime.Now.ToLongTimeString(),
AppDomain.GetCurrentThreadId))

Dim method2 As New Test2Delegate(AddressOf Test2)
Dim result As IAsyncResult = method2.BeginInvoke(New
AsyncCallback(AddressOf Test2Callback), method)

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

Jul 21 '05 #3
Sam Loveridge <sl********@adelaidebank.com.au> wrote:
Silly me. Should have triple checked the sample code. I didn't call
method2.BeginInvoke and as a result it doesn't rally highlight the problem
I'm having at all.

The threading issue I'm trying to work through revolves around the
System.Net.Sockets.Socket.BeginConnect method. My understanding of async
callbacks is that if I use a callback function it will execute on a
different thread to the main thread. However, if I use a callback function
in the BeginConnect method and note the thread it would appear to be on the
main thread. This might not be the actual problem, but after that call
everything in my app goes haywire.
How are you detecting whether or not you're on "the main thread"?
I want to call BeginConnect so that I try to connect without holding up
execution on the main thread, but if there's an error connecting I want to
retry automatically for x number of times. On success I want to then raise a
public event to notify success. I can get my code to perform the connection
attempt, and retries and after actually connecting it executes the public
"Connected" event once (traced to confirm), but when I trace the handler of
the event I see it has actually executed the number of times I tried to
connect.

Anyone else seen this? I use a similar form of code to the example I
attached earlier (which seems to perform correctly after fixing the bug :))
which leads me to suspect the way BeginConnect operates ???

Suggestions? Examples of using BeginConnect and retries with callbacks
instead of loops?


Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that. (I know it'll be similar code to what you posted
before, but it's good to see the updated version.)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #4
Hi John.
How are you detecting whether or not you're on "the main thread"?
I use "AppDomain.GetCurrentThreadId() in a trace when in various parts of my
app as it executes to debug the problem. If a callback function is supposed
to operate on a worker thread, then I would expect to see a different thread
id when in my callback to the one that is displayed in the section of code
where I call BeginConnect, but they're the same. This may indicate that
maybe something under the hood of the Socket.BeginConnect code runs slightly
different to the way other delegates and callbacks are used, or I might just
be missing the point.
Could you post a short but complete program which demonstrates the
problem?


Yes, I'll try to put something together that's a cut down version of what
I've got as it involves all sorts of business process stuff that may cloud
the issue.

Sam.
Jul 21 '05 #5
Sam Loveridge <sl********@adelaidebank.com.au> wrote:
How are you detecting whether or not you're on "the main thread"?


I use "AppDomain.GetCurrentThreadId() in a trace when in various parts of my
app as it executes to debug the problem. If a callback function is supposed
to operate on a worker thread, then I would expect to see a different thread
id when in my callback to the one that is displayed in the section of code
where I call BeginConnect, but they're the same. This may indicate that
maybe something under the hood of the Socket.BeginConnect code runs slightly
different to the way other delegates and callbacks are used, or I might just
be missing the point.


If you were to call BeginConnect from a threadpool thread to start
with, you could well see the same thread id. That's the kind of thing I
was thinking about...
Could you post a short but complete program which demonstrates the
problem?


Yes, I'll try to put something together that's a cut down version of what
I've got as it involves all sorts of business process stuff that may cloud
the issue.


Great - thanks very much :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #6
This is the point where I sneak away quietly with my tail between my legs.
As it turned out it wasn't a threading issue after all, but a place in my
code where I unwittingly added event handlers more than once, resulting in
my "Connected" event being called once after multiple connection attempts to
find it actually executed as many times as there were connection attempts. I
just moved the AddHandler statements higher up the food chain and it has
rectified the problem. In any case I've learnt a lot more about async
callbacks by digging in to the bowels of threading (a little icky, but
fascinating).

Thanks for your replies Kevin & Jon.

Regards,

Sam.
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP***********************@msnews.microsoft.co m...
Sam Loveridge <sl********@adelaidebank.com.au> wrote:
How are you detecting whether or not you're on "the main thread"?


I use "AppDomain.GetCurrentThreadId() in a trace when in various parts of my
app as it executes to debug the problem. If a callback function is supposed to operate on a worker thread, then I would expect to see a different thread id when in my callback to the one that is displayed in the section of code where I call BeginConnect, but they're the same. This may indicate that
maybe something under the hood of the Socket.BeginConnect code runs slightly different to the way other delegates and callbacks are used, or I might just be missing the point.


If you were to call BeginConnect from a threadpool thread to start
with, you could well see the same thread id. That's the kind of thing I
was thinking about...
Could you post a short but complete program which demonstrates the
problem?


Yes, I'll try to put something together that's a cut down version of what I've got as it involves all sorts of business process stuff that may cloud the issue.


Great - thanks very much :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Jul 21 '05 #7
This is the point where I sneak away quietly with my tail between my legs.
As it turned out it wasn't a threading issue after all, but a place in my
code where I unwittingly added event handlers more than once, resulting in
my "Connected" event being called once after multiple connection attempts to
find it actually executed as many times as there were connection attempts. I
just moved the AddHandler statements higher up the food chain and it has
rectified the problem. In any case I've learnt a lot more about async
callbacks by digging in to the bowels of threading (a little icky, but
fascinating).

Thanks for your replies Kevin & Jon.

Regards,

Sam.
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP***********************@msnews.microsoft.co m...
Sam Loveridge <sl********@adelaidebank.com.au> wrote:
How are you detecting whether or not you're on "the main thread"?


I use "AppDomain.GetCurrentThreadId() in a trace when in various parts of my
app as it executes to debug the problem. If a callback function is supposed to operate on a worker thread, then I would expect to see a different thread id when in my callback to the one that is displayed in the section of code where I call BeginConnect, but they're the same. This may indicate that
maybe something under the hood of the Socket.BeginConnect code runs slightly different to the way other delegates and callbacks are used, or I might just be missing the point.


If you were to call BeginConnect from a threadpool thread to start
with, you could well see the same thread id. That's the kind of thing I
was thinking about...
Could you post a short but complete program which demonstrates the
problem?


Yes, I'll try to put something together that's a cut down version of what I've got as it involves all sorts of business process stuff that may cloud the issue.


Great - thanks very much :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Jul 21 '05 #8
You're welcome, Sam.

Thanks for sharing your experience with all the people here. If you have
any questions, please feel free to post them in the community.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

Jul 21 '05 #9
Sam Loveridge <sl********@adelaidebank.com.au> wrote:
This is the point where I sneak away quietly with my tail between my legs.
As it turned out it wasn't a threading issue after all, but a place in my
code where I unwittingly added event handlers more than once, resulting in
my "Connected" event being called once after multiple connection attempts to
find it actually executed as many times as there were connection attempts. I
just moved the AddHandler statements higher up the food chain and it has
rectified the problem. In any case I've learnt a lot more about async
callbacks by digging in to the bowels of threading (a little icky, but
fascinating).


No problem - good to hear it's been solved :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: ... | last post by:
Does anyone know a good tutorial on asynchronous programming in .net AsyncCallback And IASyncResult are driving me crazy. And the msdn documentation is not really helpful on this topic I...
0
by: Santa | last post by:
I am using Fritz Onion's "Asynchronous Pages" approach as mentioned in the article http://msdn.microsoft.com/msdnmag/issues/03/06/Threading/default.aspx to increase the performance of my ASPX...
1
by: RJN | last post by:
Hi I have 2 operations to perform one is to upload data and the second is to generate report. Both take huge time(more than 20 mins and I believe by that time session would have expired) and...
9
by: Sam Loveridge | last post by:
Hi all. I'm relatively new to delegates and asynchronous threading and am running into an issue. I need to asynchronously call a method (which I'm doing with a delegate and BeginInvoke) and from...
0
by: Raymondr | last post by:
Hi, First a brief description of out application: We have a webapplication which calls a couple of webservices during one request (postback). These calls to the webservices are made concurrent...
7
by: Siv | last post by:
Hi, I have a stored procedure that I want to execute and then wait in a loop showing a timer whilst it completes and then carry on once I get notification that it has completed. The main reason...
0
by: Carly | last post by:
Hi, I am not sure I understand what is the meaning of "Execution of asynchronous code is not supported in Windows Forms threading model" - since I am able to create threads and run asynchronous...
8
by: panko | last post by:
Hello, I can't manage with asynchronous socket communication. :( I wrote a class CSocket.cs. This class is taking care of sending strings to LED display. This display is actually communicating...
6
by: =?Utf-8?B?YmlsbCB0aWU=?= | last post by:
An authoritative source claims out-of-the-box asynchronous "WebClient's implementation is flawed" in .Net 3.0. Was it fixed in .Net 3.5 or .Net 3.5 SP1? Thank you.
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.