473,722 Members | 2,240 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Async Design Question

Hello -

I am trying to write a class that has an async BeginX and EndX, plus the
regular X syncronous method. Delegates seemed like the way to go,
however, I still am having problems getting exactly what I want. Here are
my goals

1. I would like the IAsyncResult that is returned by the Begin function to
be able to be waited on or polled to check for completion.
2. The Begin function would take a callback, and the async process would
call it when the task is complete.
3. I would like to have events such as ProgressChanged that get fired as the
async process progresses.
4. The async process should be able to be cancled with a function CancelX.
5. Multiple async tasks should be able to be performed at the same time.

Are delegates the way to go? Can anyone provide me with a quick example on
how to implement this.

Thanks,
Shawn
Nov 17 '05 #1
10 2955
Shawn,

I believe that all but the last request will be able to be handled with
delegates.

Basically, create a private delegate that has the same signature as your
synchronous method. When compiled, the delegate will create BeginInvoke and
EndInvoke methods which can be used to make the call asynchronously. Then,
all you have to do is expose the methods (BeginXXX and EndXXX) with the same
signatures as the corresponding methods on the delegate.

When those methods are called, you just channel the call to a delegate
instance and return the appropriate IAsyncResult. The delegate, of course,
points to your synchronous method implementation.

The thing is, you have to store the delegate in your class instance, and
can only have one async operation at a time being performed. The reason for
this is that the delegate instance is linked to the IAsyncResult returned
from the call to BeginInvoke, and if you create a new one, it will not work.
This is the reason #5 can not be implemented. You can get around this by
creating another instance of your class, and having that perform the async
operation.

For 3 and 4, that is up to you to create the progress events and the
cancel method. Basically, you would have a flag somewhere which indicates
whether or not the operation should be cancelled. As your synchronous
method is run, it checks the flag (access to the flag should be synchronized
through the lock statement) and if the flag is set, cancel the operation,
and exit the method.

Of course, if the method has a main loop that runs, it becomes very
obvious where to check the flag to see if it is a cancelled operation.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Shawn Meyer" <me@me.com> wrote in message
news:Ok******** ******@TK2MSFTN GP10.phx.gbl...
Hello -

I am trying to write a class that has an async BeginX and EndX, plus the
regular X syncronous method. Delegates seemed like the way to go,
however, I still am having problems getting exactly what I want. Here are
my goals

1. I would like the IAsyncResult that is returned by the Begin function to
be able to be waited on or polled to check for completion.
2. The Begin function would take a callback, and the async process would
call it when the task is complete.
3. I would like to have events such as ProgressChanged that get fired as
the
async process progresses.
4. The async process should be able to be cancled with a function CancelX.
5. Multiple async tasks should be able to be performed at the same time.

Are delegates the way to go? Can anyone provide me with a quick example
on
how to implement this.

Thanks,
Shawn

Nov 17 '05 #2
(I'm not the Original Poster)

:: The reason for this is that the delegate instance is linked
:: to the IAsyncResult returned from the call to BeginInvoke,
:: and if you create a new one, it will not work. This is the
:: reason #5 can not be implemented. You can get around
:: this by creating another instance of your class, and having
:: that perform the async operation.

This is a curious remark. I don't recall reading this in the MSDN
documentation.

I created a data access component about 2 1/2 years ago (long before ADO.NET
2.0 was ever announced and even before the data access application block
ever existed) that has ability to execute readers, scalars, datasets,
datatables, and nonqueries asyncronously (I am more than happy to provide
the source code if anyone wants it, C#, and very neat and tidy). This same
component has been in 3 production environments over the years and in each
invenvironment there are close to about 3 million page requests per day. It
uses delegates internally to execute the async results, in much the same way
you described below. The only difference between what you describe and the
behaviors we receive, are that I can indeed execute as many commands as I
want simultaneously to return a datatable and all the results come back with
their proper results and the requests don't get queued. For example, if I
execute 10 commands at the same time async (on the same object instance,
delegate instance) and each command requires 3 seconds to complete, then I
only need to wait roughly 3 seconds before I have the results for all 10
commands properly.

I'm curious what you mean by your above statement?

Here's my source to demonstrate what I'm saying:

private void button1_Click(o bject sender, System.EventArg s e)
{
SqlDataHelper data = null;
DataTable x = null;
DataTable y = null;
DataTable z = null;
DataTable t = null;

try
{
data = new SqlDataHelper(c onnectionString );

IAsyncResult ar1 = data.BeginExecu teTable("SELECT * FROM Orders",
false);
IAsyncResult ar2 = data.BeginExecu teTable("SELECT TOP 5000 * FROM
Invoices", false);
IAsyncResult ar3 = data.BeginExecu teTable("SELECT TOP 10000 * FROM
AuditLog", false);

// Do something while the other 3 are still fetching
//
t = data.ExecuteTab le("SELECT * FROM SalesGroups", false);

foreach (DataRow row in t.Rows)
{
row[0] = 0;
}

data.BeginExecu teReader("SELEC T TOP 5 * FROM InventoryPieces ", false,
new AsyncCallback(C allbackMethod)) ;

// Now we synchronize
//
x = data.EndExecute Table(ar1);
y = data.EndExecute Table(ar2);
z = data.EndExecute Table(ar3);

MessageBox.Show (t.Rows.Count.T oString());
MessageBox.Show (x.Rows.Count.T oString());
MessageBox.Show (y.Rows.Count.T oString());
MessageBox.Show (z.Rows.Count.T oString());
}
finally
{
if (data != null)
{
data.Dispose();
}
}
}

public void CallbackMethod( IAsyncResult ar)
{
SqlDataHelper data = null;
IDataReader result = null;
int count = 0;

try
{
data = new SqlDataHelper(c onnectionString );

result = data.EndExecute Reader(ar);

while (result.Read()) count++;
result.Close();

MessageBox.Show ("Callback: " + count.ToString( ));
}
catch (Exception ex)
{
throw;
}
finally
{
if (data != null)
{
data.Dispose();
}
}
}
If you would like to see my data access component I'll provide you a link to
download the source code.
Thanks,
Shawn


"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om> wrote in
message news:O$******** ******@tk2msftn gp13.phx.gbl...
Shawn,

I believe that all but the last request will be able to be handled with delegates.

Basically, create a private delegate that has the same signature as your synchronous method. When compiled, the delegate will create BeginInvoke and EndInvoke methods which can be used to make the call asynchronously. Then, all you have to do is expose the methods (BeginXXX and EndXXX) with the same signatures as the corresponding methods on the delegate.

When those methods are called, you just channel the call to a delegate
instance and return the appropriate IAsyncResult. The delegate, of course, points to your synchronous method implementation.

The thing is, you have to store the delegate in your class instance, and can only have one async operation at a time being performed. The reason for this is that the delegate instance is linked to the IAsyncResult returned
from the call to BeginInvoke, and if you create a new one, it will not work. This is the reason #5 can not be implemented. You can get around this by
creating another instance of your class, and having that perform the async
operation.

For 3 and 4, that is up to you to create the progress events and the
cancel method. Basically, you would have a flag somewhere which indicates
whether or not the operation should be cancelled. As your synchronous
method is run, it checks the flag (access to the flag should be synchronized through the lock statement) and if the flag is set, cancel the operation,
and exit the method.

Of course, if the method has a main loop that runs, it becomes very
obvious where to check the flag to see if it is a cancelled operation.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Shawn Meyer" <me@me.com> wrote in message
news:Ok******** ******@TK2MSFTN GP10.phx.gbl...
Hello -

I am trying to write a class that has an async BeginX and EndX, plus the
regular X syncronous method. Delegates seemed like the way to go,
however, I still am having problems getting exactly what I want. Here are my goals

1. I would like the IAsyncResult that is returned by the Begin function to be able to be waited on or polled to check for completion.
2. The Begin function would take a callback, and the async process would
call it when the task is complete.
3. I would like to have events such as ProgressChanged that get fired as
the
async process progresses.
4. The async process should be able to be cancled with a function CancelX. 5. Multiple async tasks should be able to be performed at the same time.

Are delegates the way to go? Can anyone provide me with a quick example
on
how to implement this.

Thanks,
Shawn


Nov 17 '05 #3
Okay, I correct myself, I am creating a different delegate instance each
time the command is created, so it isn't reusing the same instance.
#region ExecuteTable Asynchronous

public virtual IAsyncResult BeginExecuteTab le(
string sqlQuery,
bool storedProcedure
)
{
ExecuteTableDel egate result = new
ExecuteTableDel egate(this.Exec uteTableAsync);
return result.BeginInv oke(sqlQuery, storedProcedure , null, null);
}

public virtual IAsyncResult BeginExecuteTab le(
string sqlQuery,
bool storedProcedure ,
AsyncCallback callback
)
{
ExecuteTableDel egate result = new
ExecuteTableDel egate(this.Exec uteTableAsync);
return result.BeginInv oke(sqlQuery, storedProcedure , callback, result);
}
public virtual DataTable EndExecuteTable (IAsyncResult ar)
{
ExecuteTableDel egate result = null;

if (ar.AsyncState != null)
{
result = (ExecuteTableDe legate)ar.Async State;
}
else
{
result = (ExecuteTableDe legate)((AsyncR esult)ar).Async Delegate;
}

ar.AsyncWaitHan dle.WaitOne();
return result.EndInvok e(ar);
}

protected virtual DataTable ExecuteTableAsy nc(
string sqlQuery,
bool storedProcedure
)
{
DbAsyncBase data = (DbAsyncBase)Ge tNewDalInstance ();
DataTable result = null;

try
{
AsyncCounter++;

foreach(IDbData Parameter param in Parameters)
{
data.Parameters .Add(param);
}

result = data.ExecuteTab le(sqlQuery, storedProcedure );
}
finally
{
if (data != null)
{
data.Dispose();
}

AsyncCounter--;
}

return result;
}
#endregion


"Shawn B." <le****@html.co m> wrote in message
news:%2******** **********@TK2M SFTNGP09.phx.gb l...
(I'm not the Original Poster)

:: The reason for this is that the delegate instance is linked
:: to the IAsyncResult returned from the call to BeginInvoke,
:: and if you create a new one, it will not work. This is the
:: reason #5 can not be implemented. You can get around
:: this by creating another instance of your class, and having
:: that perform the async operation.

This is a curious remark. I don't recall reading this in the MSDN
documentation.

I created a data access component about 2 1/2 years ago (long before ADO.NET 2.0 was ever announced and even before the data access application block
ever existed) that has ability to execute readers, scalars, datasets,
datatables, and nonqueries asyncronously (I am more than happy to provide
the source code if anyone wants it, C#, and very neat and tidy). This same component has been in 3 production environments over the years and in each
invenvironment there are close to about 3 million page requests per day. It uses delegates internally to execute the async results, in much the same way you described below. The only difference between what you describe and the behaviors we receive, are that I can indeed execute as many commands as I
want simultaneously to return a datatable and all the results come back with their proper results and the requests don't get queued. For example, if I
execute 10 commands at the same time async (on the same object instance,
delegate instance) and each command requires 3 seconds to complete, then I
only need to wait roughly 3 seconds before I have the results for all 10
commands properly.

I'm curious what you mean by your above statement?

Here's my source to demonstrate what I'm saying:

private void button1_Click(o bject sender, System.EventArg s e)
{
SqlDataHelper data = null;
DataTable x = null;
DataTable y = null;
DataTable z = null;
DataTable t = null;

try
{
data = new SqlDataHelper(c onnectionString );

IAsyncResult ar1 = data.BeginExecu teTable("SELECT * FROM Orders",
false);
IAsyncResult ar2 = data.BeginExecu teTable("SELECT TOP 5000 * FROM
Invoices", false);
IAsyncResult ar3 = data.BeginExecu teTable("SELECT TOP 10000 * FROM
AuditLog", false);

// Do something while the other 3 are still fetching
//
t = data.ExecuteTab le("SELECT * FROM SalesGroups", false);

foreach (DataRow row in t.Rows)
{
row[0] = 0;
}

data.BeginExecu teReader("SELEC T TOP 5 * FROM InventoryPieces ", false,
new AsyncCallback(C allbackMethod)) ;

// Now we synchronize
//
x = data.EndExecute Table(ar1);
y = data.EndExecute Table(ar2);
z = data.EndExecute Table(ar3);

MessageBox.Show (t.Rows.Count.T oString());
MessageBox.Show (x.Rows.Count.T oString());
MessageBox.Show (y.Rows.Count.T oString());
MessageBox.Show (z.Rows.Count.T oString());
}
finally
{
if (data != null)
{
data.Dispose();
}
}
}

public void CallbackMethod( IAsyncResult ar)
{
SqlDataHelper data = null;
IDataReader result = null;
int count = 0;

try
{
data = new SqlDataHelper(c onnectionString );

result = data.EndExecute Reader(ar);

while (result.Read()) count++;
result.Close();

MessageBox.Show ("Callback: " + count.ToString( ));
}
catch (Exception ex)
{
throw;
}
finally
{
if (data != null)
{
data.Dispose();
}
}
}
If you would like to see my data access component I'll provide you a link to download the source code.
Thanks,
Shawn


"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om> wrote in message news:O$******** ******@tk2msftn gp13.phx.gbl...
Shawn,

I believe that all but the last request will be able to be handled with
delegates.

Basically, create a private delegate that has the same signature as

your
synchronous method. When compiled, the delegate will create BeginInvoke

and
EndInvoke methods which can be used to make the call asynchronously.

Then,
all you have to do is expose the methods (BeginXXX and EndXXX) with the

same
signatures as the corresponding methods on the delegate.

When those methods are called, you just channel the call to a delegate
instance and return the appropriate IAsyncResult. The delegate, of

course,
points to your synchronous method implementation.

The thing is, you have to store the delegate in your class instance,

and
can only have one async operation at a time being performed. The reason

for
this is that the delegate instance is linked to the IAsyncResult returned from the call to BeginInvoke, and if you create a new one, it will not

work.
This is the reason #5 can not be implemented. You can get around this by creating another instance of your class, and having that perform the async operation.

For 3 and 4, that is up to you to create the progress events and the
cancel method. Basically, you would have a flag somewhere which indicates whether or not the operation should be cancelled. As your synchronous
method is run, it checks the flag (access to the flag should be

synchronized
through the lock statement) and if the flag is set, cancel the operation, and exit the method.

Of course, if the method has a main loop that runs, it becomes very
obvious where to check the flag to see if it is a cancelled operation.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Shawn Meyer" <me@me.com> wrote in message
news:Ok******** ******@TK2MSFTN GP10.phx.gbl...
Hello -

I am trying to write a class that has an async BeginX and EndX, plus the regular X syncronous method. Delegates seemed like the way to go,
however, I still am having problems getting exactly what I want. Here

are my goals

1. I would like the IAsyncResult that is returned by the Begin function to
be able to be waited on or polled to check for completion.
2. The Begin function would take a callback, and the async process
would call it when the task is complete.
3. I would like to have events such as ProgressChanged that get fired as the
async process progresses.
4. The async process should be able to be cancled with a function

CancelX. 5. Multiple async tasks should be able to be performed at the same time.
Are delegates the way to go? Can anyone provide me with a quick example on
how to implement this.

Thanks,
Shawn



Nov 17 '05 #4
Shawn,

I was a bit off my rocker when I responded to this. You could do this.
My thought was that a different delegate would be created for each
invocation of the asynchronous method, which would require the instances to
be stored on the class level, and then when you called the EndXXX method, it
would throw an exception, because the IAsyncResult implementation would not
match with the delegate that created it.

However, a simple workaround would be to just create one delegate, and
have that handle all of the asynchronous calls.

The only problem that exists for #5 is that if this is allowed, then the
progress and the cancel methods would have to have some way of indicating
which asynchronous call is being updated or cancelled.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Shawn B." <le****@html.co m> wrote in message
news:%2******** **********@TK2M SFTNGP09.phx.gb l...
(I'm not the Original Poster)

:: The reason for this is that the delegate instance is linked
:: to the IAsyncResult returned from the call to BeginInvoke,
:: and if you create a new one, it will not work. This is the
:: reason #5 can not be implemented. You can get around
:: this by creating another instance of your class, and having
:: that perform the async operation.

This is a curious remark. I don't recall reading this in the MSDN
documentation.

I created a data access component about 2 1/2 years ago (long before
ADO.NET
2.0 was ever announced and even before the data access application block
ever existed) that has ability to execute readers, scalars, datasets,
datatables, and nonqueries asyncronously (I am more than happy to provide
the source code if anyone wants it, C#, and very neat and tidy). This
same
component has been in 3 production environments over the years and in each
invenvironment there are close to about 3 million page requests per day.
It
uses delegates internally to execute the async results, in much the same
way
you described below. The only difference between what you describe and
the
behaviors we receive, are that I can indeed execute as many commands as I
want simultaneously to return a datatable and all the results come back
with
their proper results and the requests don't get queued. For example, if I
execute 10 commands at the same time async (on the same object instance,
delegate instance) and each command requires 3 seconds to complete, then I
only need to wait roughly 3 seconds before I have the results for all 10
commands properly.

I'm curious what you mean by your above statement?

Here's my source to demonstrate what I'm saying:

private void button1_Click(o bject sender, System.EventArg s e)
{
SqlDataHelper data = null;
DataTable x = null;
DataTable y = null;
DataTable z = null;
DataTable t = null;

try
{
data = new SqlDataHelper(c onnectionString );

IAsyncResult ar1 = data.BeginExecu teTable("SELECT * FROM Orders",
false);
IAsyncResult ar2 = data.BeginExecu teTable("SELECT TOP 5000 * FROM
Invoices", false);
IAsyncResult ar3 = data.BeginExecu teTable("SELECT TOP 10000 * FROM
AuditLog", false);

// Do something while the other 3 are still fetching
//
t = data.ExecuteTab le("SELECT * FROM SalesGroups", false);

foreach (DataRow row in t.Rows)
{
row[0] = 0;
}

data.BeginExecu teReader("SELEC T TOP 5 * FROM InventoryPieces ", false,
new AsyncCallback(C allbackMethod)) ;

// Now we synchronize
//
x = data.EndExecute Table(ar1);
y = data.EndExecute Table(ar2);
z = data.EndExecute Table(ar3);

MessageBox.Show (t.Rows.Count.T oString());
MessageBox.Show (x.Rows.Count.T oString());
MessageBox.Show (y.Rows.Count.T oString());
MessageBox.Show (z.Rows.Count.T oString());
}
finally
{
if (data != null)
{
data.Dispose();
}
}
}

public void CallbackMethod( IAsyncResult ar)
{
SqlDataHelper data = null;
IDataReader result = null;
int count = 0;

try
{
data = new SqlDataHelper(c onnectionString );

result = data.EndExecute Reader(ar);

while (result.Read()) count++;
result.Close();

MessageBox.Show ("Callback: " + count.ToString( ));
}
catch (Exception ex)
{
throw;
}
finally
{
if (data != null)
{
data.Dispose();
}
}
}
If you would like to see my data access component I'll provide you a link
to
download the source code.
Thanks,
Shawn


"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om> wrote
in
message news:O$******** ******@tk2msftn gp13.phx.gbl...
Shawn,

I believe that all but the last request will be able to be handled

with
delegates.

Basically, create a private delegate that has the same signature as

your
synchronous method. When compiled, the delegate will create BeginInvoke

and
EndInvoke methods which can be used to make the call asynchronously.

Then,
all you have to do is expose the methods (BeginXXX and EndXXX) with the

same
signatures as the corresponding methods on the delegate.

When those methods are called, you just channel the call to a
delegate
instance and return the appropriate IAsyncResult. The delegate, of

course,
points to your synchronous method implementation.

The thing is, you have to store the delegate in your class instance,

and
can only have one async operation at a time being performed. The reason

for
this is that the delegate instance is linked to the IAsyncResult returned
from the call to BeginInvoke, and if you create a new one, it will not

work.
This is the reason #5 can not be implemented. You can get around this by
creating another instance of your class, and having that perform the
async
operation.

For 3 and 4, that is up to you to create the progress events and the
cancel method. Basically, you would have a flag somewhere which
indicates
whether or not the operation should be cancelled. As your synchronous
method is run, it checks the flag (access to the flag should be

synchronized
through the lock statement) and if the flag is set, cancel the operation,
and exit the method.

Of course, if the method has a main loop that runs, it becomes very
obvious where to check the flag to see if it is a cancelled operation.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Shawn Meyer" <me@me.com> wrote in message
news:Ok******** ******@TK2MSFTN GP10.phx.gbl...
> Hello -
>
> I am trying to write a class that has an async BeginX and EndX, plus
> the
> regular X syncronous method. Delegates seemed like the way to go,
> however, I still am having problems getting exactly what I want. Here are > my goals
>
> 1. I would like the IAsyncResult that is returned by the Begin function to > be able to be waited on or polled to check for completion.
> 2. The Begin function would take a callback, and the async process
> would
> call it when the task is complete.
> 3. I would like to have events such as ProgressChanged that get fired
> as
> the
> async process progresses.
> 4. The async process should be able to be cancled with a function CancelX. > 5. Multiple async tasks should be able to be performed at the same
> time.
>
> Are delegates the way to go? Can anyone provide me with a quick
> example
> on
> how to implement this.
>
> Thanks,
> Shawn
>
>



Nov 17 '05 #5
I would love to see the code! It sounds very similar to what I am trying to
do.

Thanks much.
Shawn
Nov 17 '05 #6
Shawn,

The reason this works for you is that you are passing the IAsyncResult
implementation, which happens to have a reference back to the delegate that
created it. Personally, I don't think that this is a good idea, since it
wastes the slot for information, should you need to pass that around (and I
wouldn't recommend this as standard practice).

However, as you show in your code, you can always cast the IAsyncResult
implementation to the AsyncResult instance which has a reference to the
delegate that created it. It is better to use this, and free up the slot
that has the data in it.

Also, your call to WaitOne on the AsyncWaitHandle property on the async
result is not needed. When you call EndInvoke, if the call hasn't
completed, it will block until it is.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Shawn B." <le****@html.co m> wrote in message
news:uM******** ******@tk2msftn gp13.phx.gbl...
Okay, I correct myself, I am creating a different delegate instance each
time the command is created, so it isn't reusing the same instance.
#region ExecuteTable Asynchronous

public virtual IAsyncResult BeginExecuteTab le(
string sqlQuery,
bool storedProcedure
)
{
ExecuteTableDel egate result = new
ExecuteTableDel egate(this.Exec uteTableAsync);
return result.BeginInv oke(sqlQuery, storedProcedure , null, null);
}

public virtual IAsyncResult BeginExecuteTab le(
string sqlQuery,
bool storedProcedure ,
AsyncCallback callback
)
{
ExecuteTableDel egate result = new
ExecuteTableDel egate(this.Exec uteTableAsync);
return result.BeginInv oke(sqlQuery, storedProcedure , callback, result);
}
public virtual DataTable EndExecuteTable (IAsyncResult ar)
{
ExecuteTableDel egate result = null;

if (ar.AsyncState != null)
{
result = (ExecuteTableDe legate)ar.Async State;
}
else
{
result = (ExecuteTableDe legate)((AsyncR esult)ar).Async Delegate;
}

ar.AsyncWaitHan dle.WaitOne();
return result.EndInvok e(ar);
}

protected virtual DataTable ExecuteTableAsy nc(
string sqlQuery,
bool storedProcedure
)
{
DbAsyncBase data = (DbAsyncBase)Ge tNewDalInstance ();
DataTable result = null;

try
{
AsyncCounter++;

foreach(IDbData Parameter param in Parameters)
{
data.Parameters .Add(param);
}

result = data.ExecuteTab le(sqlQuery, storedProcedure );
}
finally
{
if (data != null)
{
data.Dispose();
}

AsyncCounter--;
}

return result;
}
#endregion


"Shawn B." <le****@html.co m> wrote in message
news:%2******** **********@TK2M SFTNGP09.phx.gb l...
(I'm not the Original Poster)

:: The reason for this is that the delegate instance is linked
:: to the IAsyncResult returned from the call to BeginInvoke,
:: and if you create a new one, it will not work. This is the
:: reason #5 can not be implemented. You can get around
:: this by creating another instance of your class, and having
:: that perform the async operation.

This is a curious remark. I don't recall reading this in the MSDN
documentation.

I created a data access component about 2 1/2 years ago (long before

ADO.NET
2.0 was ever announced and even before the data access application block
ever existed) that has ability to execute readers, scalars, datasets,
datatables, and nonqueries asyncronously (I am more than happy to provide
the source code if anyone wants it, C#, and very neat and tidy). This

same
component has been in 3 production environments over the years and in
each
invenvironment there are close to about 3 million page requests per day.

It
uses delegates internally to execute the async results, in much the same

way
you described below. The only difference between what you describe and

the
behaviors we receive, are that I can indeed execute as many commands as I
want simultaneously to return a datatable and all the results come back

with
their proper results and the requests don't get queued. For example, if
I
execute 10 commands at the same time async (on the same object instance,
delegate instance) and each command requires 3 seconds to complete, then
I
only need to wait roughly 3 seconds before I have the results for all 10
commands properly.

I'm curious what you mean by your above statement?

Here's my source to demonstrate what I'm saying:

private void button1_Click(o bject sender, System.EventArg s e)
{
SqlDataHelper data = null;
DataTable x = null;
DataTable y = null;
DataTable z = null;
DataTable t = null;

try
{
data = new SqlDataHelper(c onnectionString );

IAsyncResult ar1 = data.BeginExecu teTable("SELECT * FROM Orders",
false);
IAsyncResult ar2 = data.BeginExecu teTable("SELECT TOP 5000 * FROM
Invoices", false);
IAsyncResult ar3 = data.BeginExecu teTable("SELECT TOP 10000 * FROM
AuditLog", false);

// Do something while the other 3 are still fetching
//
t = data.ExecuteTab le("SELECT * FROM SalesGroups", false);

foreach (DataRow row in t.Rows)
{
row[0] = 0;
}

data.BeginExecu teReader("SELEC T TOP 5 * FROM InventoryPieces ", false,
new AsyncCallback(C allbackMethod)) ;

// Now we synchronize
//
x = data.EndExecute Table(ar1);
y = data.EndExecute Table(ar2);
z = data.EndExecute Table(ar3);

MessageBox.Show (t.Rows.Count.T oString());
MessageBox.Show (x.Rows.Count.T oString());
MessageBox.Show (y.Rows.Count.T oString());
MessageBox.Show (z.Rows.Count.T oString());
}
finally
{
if (data != null)
{
data.Dispose();
}
}
}

public void CallbackMethod( IAsyncResult ar)
{
SqlDataHelper data = null;
IDataReader result = null;
int count = 0;

try
{
data = new SqlDataHelper(c onnectionString );

result = data.EndExecute Reader(ar);

while (result.Read()) count++;
result.Close();

MessageBox.Show ("Callback: " + count.ToString( ));
}
catch (Exception ex)
{
throw;
}
finally
{
if (data != null)
{
data.Dispose();
}
}
}
If you would like to see my data access component I'll provide you a link

to
download the source code.
Thanks,
Shawn


"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om> wrote

in
message news:O$******** ******@tk2msftn gp13.phx.gbl...
> Shawn,
>
> I believe that all but the last request will be able to be handled

with
> delegates.
>
> Basically, create a private delegate that has the same signature as

your
> synchronous method. When compiled, the delegate will create
> BeginInvoke

and
> EndInvoke methods which can be used to make the call asynchronously.

Then,
> all you have to do is expose the methods (BeginXXX and EndXXX) with the

same
> signatures as the corresponding methods on the delegate.
>
> When those methods are called, you just channel the call to a delegate > instance and return the appropriate IAsyncResult. The delegate, of

course,
> points to your synchronous method implementation.
>
> The thing is, you have to store the delegate in your class
> instance,

and
> can only have one async operation at a time being performed. The
> reason

for
> this is that the delegate instance is linked to the IAsyncResult returned > from the call to BeginInvoke, and if you create a new one, it will not

work.
> This is the reason #5 can not be implemented. You can get around this by > creating another instance of your class, and having that perform the async > operation.
>
> For 3 and 4, that is up to you to create the progress events and
> the
> cancel method. Basically, you would have a flag somewhere which indicates > whether or not the operation should be cancelled. As your synchronous
> method is run, it checks the flag (access to the flag should be

synchronized
> through the lock statement) and if the flag is set, cancel the operation, > and exit the method.
>
> Of course, if the method has a main loop that runs, it becomes very
> obvious where to check the flag to see if it is a cancelled operation.
>
> Hope this helps.
>
> --
> - Nicholas Paldino [.NET/C# MVP]
> - mv*@spam.guard. caspershouse.co m
>
> "Shawn Meyer" <me@me.com> wrote in message
> news:Ok******** ******@TK2MSFTN GP10.phx.gbl...
> > Hello -
> >
> > I am trying to write a class that has an async BeginX and EndX, plus the > > regular X syncronous method. Delegates seemed like the way to go,
> > however, I still am having problems getting exactly what I want.
> > Here

are
> > my goals
> >
> > 1. I would like the IAsyncResult that is returned by the Begin function
to
> > be able to be waited on or polled to check for completion.
> > 2. The Begin function would take a callback, and the async process

would > > call it when the task is complete.
> > 3. I would like to have events such as ProgressChanged that get fired as > > the
> > async process progresses.
> > 4. The async process should be able to be cancled with a function

CancelX.
> > 5. Multiple async tasks should be able to be performed at the same time. > >
> > Are delegates the way to go? Can anyone provide me with a quick example > > on
> > how to implement this.
> >
> > Thanks,
> > Shawn
> >
> >
>
>



Nov 17 '05 #7
> The reason this works for you is that you are passing the IAsyncResult
implementation, which happens to have a reference back to the delegate that created it. Personally, I don't think that this is a good idea, since it
wastes the slot for information, should you need to pass that around (and I wouldn't recommend this as standard practice).

However, as you show in your code, you can always cast the IAsyncResult implementation to the AsyncResult instance which has a reference to the
delegate that created it. It is better to use this, and free up the slot
that has the data in it.
I will attempt to make changes as necessary to see if this can work on one
delegate instance. My memory doesn't serve anymore, but there was a reason
I did it this way after a bit of trial and error. If there's a better way,
I'll gladly make the necessary changes. This begs the question, if one
delegate instance can hold one result, how am I going to achieve the effect
of multiple executing commands?
Also, your call to WaitOne on the AsyncWaitHandle property on the async result is not needed. When you call EndInvoke, if the call hasn't
completed, it will block until it is.

I dissagree (regarding my situation but not in general). When the WaitOne
call isn't there, the same sample code I posted earlier won't work properly.
There will be unpredictable results, for example, it seems that each of the
ar1, ar2, ar3 references gets confused regarding what result it should
actually have. Sometimes all ar1, ar2, ar3 have the same results as ar1,
other times ar1 will contain ar2 and ar3 will contain ar1 results and so on.
The only way to get reliable results is to either call WaitOne yourself and
then EndExecute*, or, to have it done automatically for you (which I'm doing
here since I'm a fan of less work for the developer using the component). I
don't dissagree that when you call EndInvoke it is done (thats what I read
all the time), but for some reason, in this case, it causes unreliable
results so I had to put it there.
Thanks,
Shawn
Nov 17 '05 #8
> However, as you show in your code, you can always cast the
IAsyncResult
implementation to the AsyncResult instance which has a reference to the
delegate that created it. It is better to use this, and free up the slot
that has the data in it.


Could you elaborate on this more, specifically, when you say "it is better
to use this, and free upt he slot that has the data in it".
Thanks,
Shawn
Nov 17 '05 #9
Shawn,

Basically, the last parameter when you call BeginXXX is a state that
gets passed around during the asynchronous call. You use it to place the
IAsyncResult implementation in there. However, this isn't needed, because
the implementation holds a reference to the original delegate that created
it, which is what you are using it for in the first place.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Shawn B." <le****@html.co m> wrote in message
news:eh******** ******@TK2MSFTN GP10.phx.gbl...
However, as you show in your code, you can always cast the

IAsyncResult
implementation to the AsyncResult instance which has a reference to the
delegate that created it. It is better to use this, and free up the slot
that has the data in it.


Could you elaborate on this more, specifically, when you say "it is better
to use this, and free upt he slot that has the data in it".
Thanks,
Shawn

Nov 17 '05 #10

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

Similar topics

6
10451
by: Vanessa | last post by:
I have a question regarding async mode for calling Microsoft.XMLHTTP object. Microsoft.XMLHTTP hangs the IE once in a while suddenly, but it will work again after half an hour or so without doing anything. I have searched through the Internet and seems like the reason it hangs the browser it's because XMLHTTP limits you to two concurrent HTTP connections to each remote host; so if more than 2 concurrent connections strike the script...
8
5875
by: TS | last post by:
Im in a web page and call an asynchronous method in business class. the call back method is in the web page. When page processes, it runs thru code begins invoking the method then the page unloads. When the callback method is raised, only the method in the web page is run and the page never refreshes, it seems it all happens on the server side. I am trying to refresh the constrols on the page inside the callback method, but when id...
2
1538
by: Leneise44 | last post by:
Does the new async features within asp.net 2.0 and ado.net 2.0 render the async application block (1.1) extinct? What would be the advantages of using the async application block with 2.0? Seems like a lot less code can be written using 2.0 that threads safely and quickly.
3
2037
by: Angus | last post by:
Hello I have written my own C++ class to handle winsock. It uses an asynchronous programming model so basically you ask for something and then when network has info it gets sent to my class and I can deal with it. Basically, a user class derives from this networking class and overrides functions such as OnCompleteMessage. Sometimes, however, it is more convenient for the user class if it can call a function which then provides the...
0
1219
by: tg | last post by:
Hello, This is more of a design question. I am trying to understand how to use async web service invocation for asp.net 2.0 web parts with an Ajax style update / data rendering. I have a web page with a search box on top & 2 web parts that display search results using web services. Currently, I am calling these web services synchronously (which takes a while).
10
4504
by: Frankie | last post by:
It appears that System.Random would provide an acceptable means through which to generate a unique value used to identify multiple/concurrent asynchronous tasks. The usage of the value under consideration here is that it is supplied to the AsyncOperationManager.CreateOperation(userSuppliedState) method... with userSuppliedState being, more or less, a taskId. In this case, the userSuppliedState {really taskId} is of the object type,...
0
1575
by: Paul Hadfield | last post by:
Hi, From reading various articles on scalability issues, I understand that there is only a finite number of ASP.NET worker threads and any long running task within ASP.NET should be fired off on a seperate thread using an async call. All the articles I can find are either on implementing an async webpage, or calling an async webservice. I can not however find any article on how to make calls within a webservice asynchronous. Consider...
3
2543
by: Giulio Petrucci | last post by:
Hi there, I'm quite a newbie in Web Service programming/using and I'm sorry if my question could sound quite "stupid". ;-) I'm working on an application which should request a service to a WebService, calling its method "FooMethod(...args...)". I've imported the web reference within my VisualStudio project and tryed to invoke the method. I noticed that the intellisense expose also: - an "AsyncFooMethod(...args...(+1 overloads))";
3
3576
by: Ryan Liu | last post by:
Hi, Is Async I/O (e.g. NetworkStream.Begin/End Read/Write) always better than synchronous I/O? At least as good? When I don't concern about easy or difficult to write code, should I always use Async I/O?
0
8863
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8739
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9384
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9238
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9088
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
5995
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 then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4762
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3207
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2602
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.