Xamarin 中的错误 Android 带有进度对话框“只有创建视图层次结构的原始线程才能触及它的视图”

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

我正在尝试使用进度对话框,同时填充数据网格,但出现以下错误:"Only the original thread that created a view hierarchy can touch its views",这是我的代码,希望他们能帮助我

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();
            }
        }

错误告诉您应用的 UI 必须由主线程处理。在您的代码中,您在后台线程 (ThreadPool.QueueUserWorkItem) 上 运行 一些代码,而这些代码需要在 UI 线程 (RunOnUiThread) 上 运行。

您不能使用 dlg.Dismiss();在 ThreadPool.QueueUserWorkItem 内,在尝试关闭符号

之前移动它

为什么不改用 Task?

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

它看起来并没有好很多,但至少它没有未使用的标识符。

注意:Task.Run() 是 .Net 4.5 或更高版本。如果您使用的是 .Net 4,则必须执行以下操作:

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

以上两者都使用了线程池。

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

正如@CaPorter 所说,应用程序的UI 必须由主线程处理There are any number of ways to get code to execute on the UI thread,你可以尝试使用 Looper.MainLooperHandler.Post()

像这样修改您的代码:

ThreadPool.QueueUserWorkItem(d => {

    ...

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