In this code, we launch the "asynchronous" operation and wait until it finished polling the .IsCompleted property of IAsyncResult.
byte[] b = new byte[1000]; // Open the stream FileStream fs = new FileStream("C:\\ike.zip", FileMode.Open, FileAccess.Read); // Start the asynchronous operation IAsyncResult ar = fs.BeginRead(b, 0, b.Length, null, null); // Wait until task is completed while (!ar.IsCompleted) { Thread.Sleep(1000); MessageBox.Show("not yet"); } MessageBox.Show("Completed" + fs.EndRead(ar).ToString()); fs.Close();But, we really want to perform some asynchronous operation, so, we need to declare the asynchronous callback method like this:
private void MyAsyncCallback(IAsyncResult ar) { FileStream fs = ar.AsyncState as FileStream; try { MessageBox.Show("Completed" + fs.EndRead(ar).ToString()); } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } finally { fs.Close(); } }And call the BeginRead as:
byte[] b = new byte[1000]; FileStream fs = new FileStream("C:\\ike.zip", FileMode.Open, FileAccess.Read); IAsyncResult ar = fs.BeginRead(b, 0, b.Length, new AsyncCallback(MyAsyncCallback), fs);Points of interest:
- We use the AsyncState parameter to pass some important object to the callback method.
- Also, if some exception is thrown in the asynchronous operation, we'll be notified only when we call the EndRead method, so, we catch the exception in the callback.
Synchronizing UI Elements:
If we try to access UI elements in another thread than they were created, an exception will be raised, to avoid that, we can ask for the property InvokeRequired in some UI elements such as forms, text boxes, list views, etc. When this property is true, we need to call the appropriated Invoke method as follows:
// Delegate declaration public delegate void ShowResult(string message); // Callback method private void MyAsyncCallback(IAsyncResult ar) { FileStream fs = ar.AsyncState as FileStream; try { ShowResultInt("Completed" + fs.EndRead(ar).ToString()); } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } finally { fs.Close(); } } private void ShowResultInt(string message) { if (txtResult.InvokeRequired) // Invoke is required, we are in another thread than UI elements txtResult.Invoke(new ShowResult(ShowResultInt), message); else // Not invoke required, then we can access UI elements directly txtResult.Text = message; }