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 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
(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
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
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 > >
I would love to see the code! It sounds very similar to what I am trying to
do.
Thanks much.
Shawn
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 > > > > > >
> 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
> 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
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
This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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...
|
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...
|
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.
|
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...
|
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).
| |
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,...
|
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...
|
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))";
|
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?
|
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...
|
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,...
| |
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...
|
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...
|
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...
|
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();...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |