i have a long running function¹:
public string FindPasswordFromHash(String hash) { ... }
which is called like:
private void Button1_Click(object sender, EventArgs e) { PasswordTextBox.Text = FindPasswordFromHash(HashTextBox.Text); }
Now i want to convert it into the asynchronous BeginInvoke/EndInvoke delegate pattern:
private void Button1_Click(object sender, EventArgs e) { MyAsyncDelegate asyncDelegate = new MyAsyncDelegate(HashTextBox.Text); asyncDelegte.BeginInvoke(hash, CompleteCallback, null); } private void CompleteCallback(IAsyncResult ar) { MyAsyncDelegate asyncDelegate = ((AsyncResult)ar).AsyncDelegate; PasswordTextBox.Text = asyncDelegate.EndInvoke(asyncResult); } delegate string MyAsyncDelegate(String hash);
Of course this doesn’t work because of a leaky abstraction of the way asynchronous delegates are implemented:
‘Cross-thread operation not valid: Control ‘PasswordTextBox’ accessed from a thread other than the thread it was created on.’
Given that the asynchronous delegate pattern was invented to convert long running operations into asynchronous operations – what is the proper technique to use BeginInvoke/EndInvoke as replacement for the synchronous call?
And more specifically, what is the method to force the callback to marshalled back to the calling thread?
¹ Function name invented for example
You are handling the BeginInvoke() and EndInvoke() calls correctly. You just need to handle the fact that manipulating the GUI needs to be done on the GUI-thread.
Luckily the framework provides the Control.Invoke() method, which allows you to have code executed on the GUI thread.
I usually do something like this:
For this particular case, you could also just do
If you using C# 2.0, you would do:
or