ObjectDisposedException

ObjectDisposedException

我开始在MacBook Pro上使用Xamarin Studio开发Xamarin.Forms。我构建了一个应用程序,其目的是查询PrestaShop网站,检索产品并显示它们。

将应用程序部署到Android时,棉花糖以下的版本存在一些问题,但我已解决了这些问题,因此在此不再赘述。

将应用程序部署到iOS(模拟器)时,我仍然遇到严重问题。该应用程序运行,但是当我单击该按钮以检索数据时,它崩溃,给了我System.ObjectDisposedException,其消息是“CancellationTokenSource已被处置”。我将在此处粘贴相关的源代码:

async void button1_Click(object sender, System.EventArgs e)
{
    try
    {
        HttpClientHandler hnd = new HttpClientHandler();
        hnd.Credentials = new NetworkCredential("[apikey]", "");
        string res;
        using (var client = new HttpClient(hnd))
        {
            var responseText = await client.GetStringAsync("[endpoint]/products");
            using (MemoryStream stream = new MemoryStream())
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write(responseText.Replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", string.Empty));
                writer.Flush();
                stream.Position = 0;
                XDocument doc = XDocument.Load(stream);
                res = JsonConvert.SerializeXNode(doc, Formatting.Indented, true);
            }
            var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(res);
            //Result.Text = data["products"].GetType().ToString() + Result.Text;
            Func<string, Task> creator_method = async (string id) =>
            {
                try
                {
                    var responseProd = await client.GetStringAsync($"[endpoint]/products/{id}"); // AT THIS ROW THE EXCEPTION IS RAISED!!!
                    using (MemoryStream stream = new MemoryStream())
                    using (StreamWriter writer = new StreamWriter(stream))
                    {
                        writer.Write(responseProd.Replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", string.Empty));
                        writer.Flush();
                        stream.Position = 0;
                        XDocument doc = XDocument.Load(stream);
                        res = JsonConvert.SerializeXNode(doc, Formatting.Indented, true);
                    }
                    var product_rawData = JsonConvert.DeserializeObject<Dictionary<string, object>>(res);
                    var productData = (JObject)product_rawData["product"];
                    try
                    {
                        views.Children.Add(new ProductXaml(productData["name"]["language"]["#cdata-section"].ToString(), float.Parse(productData["price"]["#cdata-section"].ToString().Replace('.', ',')), productData["id_default_image"]["@xlink:href"].ToString()));
                    }
                    catch (NullReferenceException nre)
                    {
                        views.Children.Add(new ProductXaml(productData["name"]["language"]["#cdata-section"].ToString(), float.Parse(productData["price"]["#cdata-section"].ToString().Replace('.', ',')), ""));
                    }
                }
                catch (Exception gex) { throw; }
            };
            foreach (var product in ((JObject)data["products"])["product"])
                try
                {
                    Device.BeginInvokeOnMainThread(async () => { await creator_method.Invoke(product["@id"].ToString()); });
                }
                catch (TaskCanceledException tce) { continue; }
                catch (WebException we) { continue;}
        }
    }
    catch (HttpRequestException ex)
    {
        Result.Text = ex.Message;
    }
}

我该如何解决这个问题?

最佳答案



您的using (var client = new HttpClient())...CancellationToken似乎已被第一个client.GetStringAsync()调用所占用。

如何修复此
为了避免这种情况,建议您将第二个调用放在自己的using块中。

这是您的代码现在的样子,带有第二个using语句:

async void button1_Click(object sender, System.EventArgs e)
{
    try
    {
        HttpClientHandler hnd = new HttpClientHandler();
        hnd.Credentials = new NetworkCredential("[apikey]", "");
        string res;
        using (var client = new HttpClient(hnd))
        {
            var responseText = await client.GetStringAsync("[endpoint]/products");
            using (MemoryStream stream = new MemoryStream())
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write(responseText.Replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", string.Empty));
                writer.Flush();
                stream.Position = 0;
                XDocument doc = XDocument.Load(stream);
                res = JsonConvert.SerializeXNode(doc, Formatting.Indented, true);
            }
            var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(res);
            //Result.Text = data["products"].GetType().ToString() + Result.Text;
            Func<string, Task> creator_method = async (string id) =>
            {
                try
                {
                    using (var newClient = new HttpClient(hnd)) // Create a new client to avoid your other one's token being consumed
                    {
                        var responseProd = await newClient.GetStringAsync($"[endpoint]/products/{id}");
                        using (MemoryStream stream = new MemoryStream())
                        using (StreamWriter writer = new StreamWriter(stream))
                        {
                            writer.Write(responseProd.Replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", string.Empty));
                            writer.Flush();
                            stream.Position = 0;
                            XDocument doc = XDocument.Load(stream);
                            res = JsonConvert.SerializeXNode(doc, Formatting.Indented, true);
                        }
                        var product_rawData = JsonConvert.DeserializeObject<Dictionary<string, object>>(res);
                        var productData = (JObject)product_rawData["product"];
                        try
                        {
                            views.Children.Add(new ProductXaml(productData["name"]["language"]["#cdata-section"].ToString(), float.Parse(productData["price"]["#cdata-section"].ToString().Replace('.', ',')), productData["id_default_image"]["@xlink:href"].ToString()));
                        }
                        catch (NullReferenceException nre)
                        {
                            views.Children.Add(new ProductXaml(productData["name"]["language"]["#cdata-section"].ToString(), float.Parse(productData["price"]["#cdata-section"].ToString().Replace('.', ',')), ""));
                        }
                    }
                }
                catch (Exception gex) { throw; }
            };
            foreach (var product in ((JObject)data["products"])["product"])
                try
                {
                    Device.BeginInvokeOnMainThread(async () => { await creator_method.Invoke(product["@id"].ToString()); });
                }
                catch (TaskCanceledException tce) { continue; }
                catch (WebException we) { continue;}
        }
    }
    catch (HttpRequestException ex)
    {
        Result.Text = ex.Message;
    }
}

希望这可以帮助! :)

关于c# - ObjectDisposedException : The CancellationTokenSource has been disposed,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38010374/

10-10 08:58