Brain Teaser: IAsyncResult AsyncState is null after callback in Async ASP .Net Page
I could really do with some help on this one - I am completely stuck :-(
I have implemented the Async pattern (correctly, hopefully) in a search component that I have developed. This is being called from an Async Asp. Net page, using RegisterAsyncTask.
When my component completes its work it calls the supplied callback, passing an AsyncResult with the AsyncState set to a value. The debugger confirms that the value is not null when the callback is called.
When the AsyncResult arrives as the parameter to the callback function on the page's main thread - The AsyncState property is null.
This is the relevant sections of the search component:
public virtual IAsyncResult BeginSearchAsync(
Object sender,
EventArgs e,
AsyncCallback cb,
object state)
{
_callback = cb;
//... Some code
// Start the asynchronous operation.
WorkerEventHandler workerDelegate = new WorkerEventHandler(SearchWorker);
return workerDelegate.BeginInvoke(
paramz.terms,
paramz.sourceName,
asyncOp,
cb,
null);
}
protected void OnSearchCompleted(SearchCompleteEventArgs e)
{
if (_callback != null)
{
//SearchAsyncResult implements IAsyncResult
SearchAsyncResult result = new SearchAsyncResult();
result.IsCompleted = true;
result.CompletedSynchronously = true;
result.AsyncState = "TEST";
//result.AsyncState = e;
//at this point RESULT.ASYNCSTATE IS NEVER NULL!!!
_callback(result);
}
}
This is the code from the calling page's codebehind (this page has Async=true and an AsyncTimeout value set):
void searchSubmit_Click(object sender, EventArgs e)
{
foreach (RadPanelItem item in resultsPanelBar.GetAllItems())
{
//... Some Code
SearchEngine engine = new SearchEngine();
var task = new PageAsyncTask(engine.BeginSearchAsync, EndSearch, null, srchParameters, true);
RegisterAsyncTask(task);
}
}
void EndSearch(IAsyncResult asyncResult)
{
if (asyncResult.AsyncState == null)
return;
//asyncResult.Asyn开发者_JS百科cState: IS ALWAYS NULL!!!
SearchCompleteEventArgs result
= (SearchCompleteEventArgs)asyncResult.AsyncState;
}
The short answer is - I didn't do my research thoroughly. There are numerous problems with the code above.
The most significant (which is now obvious to me), is that the IAsyncResultObject returned from the BeginSearchAsync method, must be retained in the component. This object is then updated by the component during its operation. These changes are monitored by the thread that started the operation.
Once the component has finished it's work, it must set the AsyncOperation as completed and store any return value required in that same object.
The implementation of IAsyncResult is beyond trivial.
This is the article that cleared up my understanding of what was going on, and gave me a concrete implementation to start from to get a suitable AsyncResult class for my scenario:
http://msdn.microsoft.com/en-us/magazine/cc163467.aspx
精彩评论