Hi
I am trying to get a ProgressDialog to disappear when an async task I run returns.
I have followed the post at: https://forums.xamarin.com/discussion/2311/get-a-progressdialog-to-show
But this is the reverse of what I am trying to achieve because the async task is executed correctly but the ProgressDialog disappears immediately afterward.
What I need is for the ProgressDialog to appear and continue spinning and to then disappear when 'doRestfulIdCheck' returns.
My code currently is (I have omitted code and function in the class which are not relevant):
public class IDCheckFragment : Fragment { Activity fragsIDActivity{ get; set;} ImageView photoImageView{ get; set;} View globalView { get; set;} jsonIDCheckRequestStatus dataReturnedForIdCheck{ get; set;} json_IDCheck postIDCheckData; View progressOverlay; ProgressDialog viewProgressDialog; public override void OnCreate (Bundle savedInstanceState) { base.OnCreate (savedInstanceState); // Create your fragment here fragsIDActivity = Activity; } public override void OnActivityResult (int requestCode, Result resultCode, Intent data) { base.OnActivityResult (requestCode, resultCode, data); ...Omitted code... // // viewProgressDialog is declared at top of class as follows: // private ProgressDialog viewProgressDialog; // viewProgressDialog = ProgressDialog.Show(fragsIDActivity, "Please wait...", "Processing ID Check...", true); new Thread (new ThreadStart (delegate { this.doRestfulIdCheck (); fragsIDActivity.RunOnUiThread (() => viewProgressDialog.Hide ()); // Need this to occur once doRestfulIdCheck has returned })).Start (); // Putting 'viewProgressDialog.Hide ()' here the ProgressDialog never disappears even after doRestfulIdCheck returns } // Do a RESTful request - Takes about 20 seconds private async void doRestfulIdCheck() { this.dataReturnedForIdCheck = new jsonIDCheckRequestStatus(); DruidRest restDataMngr = new DruidRest (SingletonAppSettngs.Instance ().baseApiUri); this.dataReturnedForIdCheck = await restDataMngr.postIDCheckAsync(this.postIDCheckData); var textViewOutputResult = globalView.FindViewById<TextView> (Resource.Id.textViewOutputResult); textViewOutputResult.Text = "div_check_status: " + this.dataReturnedForIdCheck.div_check_status; } }
A whole bunch of stuff wrong here.
First the doRestfulIdCheck method should return type of Task. You should never use async void except in the case of a top level event handler. The callback does not work if you return void.
In OnActivityResult you absolutely should not be trying to create your own thread with async/await and IO completion ports. That one you do want to mark as async void because, unlike doRestfulIdCheck, it is a top level event handler that you don't control the return type for. The methods should look more like this (haven't tested it at all):
`
public override async void OnActivityResult (int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult (requestCode, resultCode, data);
...Omitted code... // // viewProgressDialog is declared at top of class as follows: // private ProgressDialog viewProgressDialog; // viewProgressDialog = ProgressDialog.Show(fragsIDActivity, "Please wait...", "Processing ID Check...", true); await DoRestfulIdCheckAsync(); // this code only happens after the DoRestfulIdCheckAsync method completes, acts as a callback. fragsIDActivity.RunOnUiThread (() => viewProgressDialog.Hide ()); // Need this to occur once doRestfulIdCheck has returned } // Do a RESTful request - Takes about 20 seconds private async Task DoRestfulIdCheckAsync() { this.dataReturnedForIdCheck = new jsonIDCheckRequestStatus(); DruidRest restDataMngr = new DruidRest (SingletonAppSettngs.Instance ().baseApiUri); // As soon as the awated method is called, the current thread is released. this.dataReturnedForIdCheck = await restDataMngr.postIDCheckAsync(this.postIDCheckData); // this code only happens after the postIDCheckAsync method completes, acts as a callback. var textViewOutputResult = globalView.FindViewById<TextView> (Resource.Id.textViewOutputResult); textViewOutputResult.Text = "div_check_status: " + this.dataReturnedForIdCheck.div_check_status; } `
Answers
A whole bunch of stuff wrong here.
First the doRestfulIdCheck method should return type of Task. You should never use async void except in the case of a top level event handler. The callback does not work if you return void.
In OnActivityResult you absolutely should not be trying to create your own thread with async/await and IO completion ports. That one you do want to mark as async void because, unlike doRestfulIdCheck, it is a top level event handler that you don't control the return type for. The methods should look more like this (haven't tested it at all):
`
public override async void OnActivityResult (int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult (requestCode, resultCode, data);
Hi @KevinFord
Ok many thanks, your explanation was very helpful, made me understand how this should work.
What I failed to mention was that the x method actually returns a Task already as follows:
This method is already a member of a shared library I created for handling all my REST stuff and is working 100% on my iOS part of this PCL build. Seems the syntax and calls for threaded stuff differs between iOS and Android.
My code is now as follows (I completely omitted the DoRestfulIdCheck call) after using your explanation to adjust and it now works 100%:
Many thanks for the help and explanation Kevin.
Best Regards
John
Great answer. After 2 days I got the solution. Thanks