System. Windows. Forms. Timer is always executed on the main thread (that is, the UI thread)
1. Define a delegate
Public Delegate int dosomethingdelegate (INT input );
2. Define a class. The method in the class matches the signature with the delegate.
Public class myobject
{
Public int doublenumber (INT input)
{
Return input * 2;
}
}
3. Create a delegate to point to the class Method
Myobject myobj = new myobject ();
// Create a delegate that points to the myobj. doublenumber () method.
Dosomethingdelegate dosomething = new dosomethingdelegate (myobj. doublenumber );
// Call the myobj. doublenumber () method through the delegate.
Int doublevalue = dosomething (12 );
What you may not realize is that delegates
Directly calling the delegate method is actually using the invoke method, which synchronously executes related functions.
Another begininvoke method is used to asynchronously execute related functions.
Iasyncresult async = dosomething. begininvoke (12, null, null );
However, the execution result of the function is not returned. The parameter is the original parameter + callback object + status object.
After the preceding example is rewritten using an Asynchronous Method:
Myobject myobj = new myobject ();
// Create a delegate that points to the myobj. doublenumber () method.
Dosomethingdelegate dosomething = new dosomethingdelegate (myobj. doublenumber );
// Start the myobj. doublenumber () method on another thread.
Iasyncresult async = dosomething. begininvoke (originalvalue, null, null); // returns an iasyncresult object.
// (Do something else here while myobj. doublenumber () is executing .)
// Retrieve the results, and wait (synchronously) if they're still not ready.
Int doublevalue = dosomething. endinvoke (async); // obtain the value through the iasyncresult object.
■
When you call an Asynchronous Method, CLR calls the threads in its thread pool to use it. The thread pool size is generally single CPU and 25 threads.
Round Robin and callback
When you call endinvoke (), the call becomes synchronous. That is to say, if the call does not return, the program needs to wait.
You can use the iasyncresult. iscompleted attribute to query
Iasyncresult async = dosomething. begininvoke (12, null, null );
// Loop until the method is complete.
While (! Async. iscompleted)
{
// Do a small piece of work here.
}
Int doublevalue = dosomething. endinvoke (async );
Efficiency is not very high.
A better choice is to use the callback method.
// The callback method uses the iasyncresult object as the parameter
Private void mycallback (iasyncresult async)
{...}
Use of callback Methods
Dosomething. begininvoke (12, new asynccallback (this. mycallback), null );
The callback method does not know who triggered the callback. That is to say, if the callback method corresponds to multiple asynchronous operations, it does not know which operation is completed.
To cancel this restriction, you can assign a value to the last parameter of the begininvoke method.
Then obtain the information through iasyncresult. asyncstate.
A useful technique is to use a delegate object as a State object.
Dosomething. begininvoke (originalvalue,
New asynccallback (this. mycallback), dosomething );
The callback method is as follows:
Private void mycallback (iasyncresult async)
{
// Retrieve the delegate.
Dosomethingdelegate dosomething = (dosomethingdelegate) async. asyncstate;
// Use it to retrieve the result.
Int doublevalue = dosomething. endinvoke (async );
// (Do something with the retrieved information .)
}
The callback method is in the same thread as the asynchronous execution method, rather than in the main thread (ui thread.
An example in Windows Forms
Code 1:
Public class worker
{
Public static int [] findprimes (INT fromnumber, int tonumber)
{
// Find the primes between fromnumber and tonumber,
// And return them as an array of integers.
}
}
Code 2:
Private void upload find_click (Object sender, eventargs E)
{
This. usewaitcursor = true;
Txtresults. Text = "";
Lbltimetaken. Text = "";
// Get the search range.
Int from,;
If (! Int32.tryparse (txtfrom. Text, out from ))
{
MessageBox. Show ("invalid from value .");
Return;
}
If (! Int32.tryparse (txw.text, out ))
{
MessageBox. Show ("invalid to value .");
Return;
}
// Start the search for PRIMES and wait.
Datetime starttime = datetime. now;
Int [] primes = worker. findprimes (from, );
// Display the time for the call to complete.
Lbltimetaken. Text =
Datetime. Now. Subtract (starttime). totalseconds. tostring ();
// Paste the list of primes together into one long string.
Stringbuilder sb = new stringbuilder ();
Foreach (INT prime in primes)
{Sb. append (prime. tostring ());
SB. append ("");
}
Txtresults. Text = sb. tostring ();
This. usewaitcursor = false;
}
In this case, the interface cannot be operated during execution.
Asynchronous execution:
Code 1: Execute asynchronous operations and update the interface
Private void callasyncworker (int from, int)
{
// Start the search for PRIMES and wait.
Datetime starttime = datetime. now;
Int [] primes = worker. findprimes (from, );
// Calculate the time for the call to complete.
Timespan timetaken = datetime. Now. Subtract (starttime );
// Paste the list of primes together into one long string.
Stringbuilder sb = new stringbuilder ();
Foreach (INT prime in primes)
{
SB. append (prime. tostring ());
SB. append ("");
}
// Use the control. Invoke () method of the current form,
// Which is owned by the same thread as the rest of the controls.
// Update the result directly in the asynchronous execution method without using a callback function.
This. Invoke (New updateformdelegate (updateform ),
New object [] {timetaken, SB. tostring ()});
}
Code 2:
Private delegate void callasyncworkerdelegate (int from, int );
Code 3:
Private void upload find_click (Object sender, eventargs E)
{
// Disable the button.
Optional find. Enabled = false;
Txtresults. Text = "";
Lbltimetaken. Text = "";
// Get the search range.
Int from,;
If (! Int32.tryparse (txtfrom. Text, out from ))
{
MessageBox. Show ("invalid from value .");
Return;
}
If (! Int32.tryparse (txw.text, out ))
{
MessageBox. Show ("invalid to value .");
Return;
}
// Start the search for primes on another thread.
Callasyncworkerdelegate dowork = new
Callasyncworkerdelegate (callasyncworker );
Dowork. begininvoke (from, to, null, null );
}
Code 4
Private delegate void updateformdelegate (timespan timetaken, string primelist );
Code 5
Private void updateform (timespan timetaken, string primelist)
{
Lbltimetaken. Text = timetaken. totalseconds. tostring ();
Txtresults. Text = primelist;
Optional find. Enabled = true;
}