Oscar Navarro
Oscar Navarro

Reputation: 151

Error in Xamarin Android with a progress dialog “Only the original thread that created a view hierarchy can touch its views”

I'm trying to use a progress dialog, while filling a datagrid, but I get the following error: "Only the original thread that created a view hierarchy can touch its views", this is my code, i hope they can help me

public async void RelacionClientesREST()
        {
            try
            {
                var dlg = ProgressDialog.Show(this, "Loading", "Cargando relación de usuarios");
                ThreadPool.QueueUserWorkItem(d => {

                    RestClient client = new RestClient("http://portalclientewa.azurewebsites.net/api/RelacionClientes/");
                    var request = new RestRequest("GetData", Method.GET);
                    request.Timeout = 1500000;
                    request.RequestFormat = DataFormat.Json;
                    request.AddParameter("idP", Idp);
                    var temp = client.Execute(request).Content;
                    var parsedJson = JsonConvert.DeserializeObject(temp).ToString();
                    var lst = JsonConvert.DeserializeObject<List<ClientesProp>>(parsedJson).ToList();
                    dataGrid.ItemsSource = lst;

                    RunOnUiThread(() => {
                        dlg.Dismiss();
                    });
                });
            }
            catch (Exception ex)
            {
                Toast.MakeText(this, "No hay datos registrados", ToastLength.Short).Show();
            }
        }

Upvotes: 1

Views: 1088

Answers (4)

York Shen
York Shen

Reputation: 9084

Only the original thread that created a view hierarchy can touch its views

As @CaPorter said, the app's UI must be handled by the main thread. There are any number of ways to get code to execute on the UI thread, you could try using Looper.MainLooper with Handler.Post().

Modify your code like this :

ThreadPool.QueueUserWorkItem(d => {

    ...

    Handler handler = new Handler(Looper.MainLooper);
    Action action = () =>
    { 
        dataGrid.ItemsSource = lst;
        dlg.Dismiss();
    };
    handler.Post(action);
});

Upvotes: 1

Sagar Panwala
Sagar Panwala

Reputation: 922

why not use Task instead?

Task.Run(() => doStuff("hello world"));

It doesn't really seem a lot better, but at least it doesn't have an unused identifier.

Note: Task.Run() is .Net 4.5 or later. If you're using .Net 4 you have to do:

Task.Factory.StartNew(() => doStuff("hello world"));

Both of the above do use the thread pool.

Upvotes: 1

you cannot use dlg.Dismiss(); inside ThreadPool.QueueUserWorkItem, move it before try close sign

Upvotes: 1

CaPorter
CaPorter

Reputation: 501

The error is telling you the app's UI must be handled by the main thread. In your code, you are running some code on a background thread (ThreadPool.QueueUserWorkItem) that needs to be run on the UI thread (RunOnUiThread) instead.

Upvotes: 1

Related Questions